continue implementing new graphics engine

* implement OpenGL ES 1.1 and OpenGL ES 2.0 support
* new framebuffer that can run on any opengl implementation
* fixes in outfit size rendering
master
Eduardo Bart 12 years ago
parent 58d76e255d
commit f14706206a

@ -7,7 +7,7 @@ INCLUDE(src/otclient/CMakeLists.txt)
# functions map for reading backtraces
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -Wl,-Map=otclient.map")
OPTION(USE_PCH "Use precompiled header (speed up compile)" OFF)
OPTION(PCH "Use precompiled header (speed up compile)" OFF)
SET(executable_SOURCES src/main.cpp)
@ -27,13 +27,13 @@ ADD_EXECUTABLE(otclient ${framework_SOURCES} ${otclient_SOURCES} ${executable_SO
# target link libraries
TARGET_LINK_LIBRARIES(otclient ${framework_LIBRARIES})
IF(USE_PCH)
IF(PCH)
FIND_PACKAGE(PCHSupport REQUIRED)
ADD_PRECOMPILED_HEADER(otclient ${CMAKE_CURRENT_SOURCE_DIR}/src/framework/pch.h)
MESSAGE(STATUS "Use precompiled header: ON")
ELSEIF(USE_PCH)
ELSE()
MESSAGE(STATUS "Use precompiled header: OFF")
ENDIF(USE_PCH)
ENDIF()
# installation
SET(DATA_INSTALL_DIR share/otclient)

@ -23,7 +23,7 @@ Window
anchors.top: outfitName.bottom
anchors.left: outfitName.left
margin-top: 5
padding: 16 4 4 16
padding: 4 4 4 4
fixed-creature-size: true
Panel

@ -6,43 +6,79 @@ ENDIF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 6)
# add framework cmake modules
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake;${CMAKE_MODULE_PATH}")
OPTION(USE_OPENGL_ES2 "Use OpenGL ES 2.0 (for mobiles devices)" OFF)
OPTION(CRASH_HANDLER "Generate crash reports" ON)
SET(BUILD_REVISION "custom" CACHE "Git revision string (intended for releases)" STRING)
OPTION(LUAJIT "Use lua jit" OFF)
SET(OPENGLES "OFF" CACHE "Use OpenGL ES 1.0 or 2.0 (for mobiles devices)" STRING)
SET(BUILD_REVISION "custom" CACHE "Git revision string (intended for releases)" STRING)
# set debug as default build type
IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo)
ENDIF()
# setup compiler options
SET(CXX_WARNS "-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-but-set-variable")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNS} -std=gnu++0x -pipe")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CXX_WARNS} -pipe")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -ggdb")
SET(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -ggdb")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O1 -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "-Os -ffast-math")
SET(CMAKE_C_FLAGS_RELEASE "-Os -ffast-math")
SET(CMAKE_CXX_FLAGS_RELFORPERFORMANCE "-Ofast -mmmx -msse -msse2")
SET(CMAKE_C_FLAGS_RELFORPERFORMANCE "-Ofast -mmmx -msse -msse2")
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -static-libgcc -static-libstdc++ -Wl,--as-needed")
MESSAGE(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
ADD_DEFINITIONS(-D"BUILD_TYPE=\\\"${CMAKE_BUILD_TYPE}\\\"")
MESSAGE(STATUS "Build revision: ${BUILD_REVISION}")
ADD_DEFINITIONS(-D"BUILD_REVISION=\\\"${BUILD_REVISION}\\\"")
# find needed libraries
IF(WIN32)
SET(Boost_THREADAPI win32)
ENDIF()
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost COMPONENTS system REQUIRED)
IF(USE_OPENGL_ES2)
IF(OPENGLES STREQUAL "2.0")
FIND_PACKAGE(OpenGLES2 REQUIRED)
FIND_PACKAGE(EGL REQUIRED)
ADD_DEFINITIONS(-DOPENGL_ES2)
SET(OPENGL_INCLUDE_DIR ${EGL_INCLUDE_DIR} ${OPENGLES_INCLUDE_DIR})
SET(OPENGL_LIBRARIES ${EGL_LIBRARY} ${OPENGLES_LIBRARY})
ADD_DEFINITIONS(-DOPENGL_ES=2)
SET(OPENGL_INCLUDE_DIR ${EGL_INCLUDE_DIR} ${OPENGLES2_INCLUDE_DIR})
SET(OPENGL_LIBRARIES ${EGL_LIBRARY} ${OPENGLES2_LIBRARY})
SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl2.cpp)
ELSEIF(OPENGLES STREQUAL "1.0")
FIND_PACKAGE(OpenGLES1 REQUIRED)
FIND_PACKAGE(EGL REQUIRED)
ADD_DEFINITIONS(-DOPENGL_ES=1)
SET(OPENGL_INCLUDE_DIR ${EGL_INCLUDE_DIR} ${OPENGLES1_INCLUDE_DIR})
SET(OPENGL_LIBRARIES ${EGL_LIBRARY} ${OPENGLES1_LIBRARY})
SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl1.cpp)
ELSE()
FIND_PACKAGE(OpenGL REQUIRED)
FIND_PACKAGE(GLEW REQUIRED)
SET(OPENGL_LIBRARIES ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl1.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl2.cpp)
ENDIF()
MESSAGE(STATUS "OpenGL ES: " ${OPENGLES})
IF(LUAJIT)
FIND_PACKAGE(LuaJIT REQUIRED)
ELSE()
FIND_PACKAGE(Lua REQUIRED)
ENDIF()
MESSAGE(STATUS "LuaJIT: " ${LUAJIT})
FIND_PACKAGE(PhysFS REQUIRED)
FIND_PACKAGE(GMP REQUIRED)
@ -52,33 +88,6 @@ FIND_PACKAGE(VorbisFile REQUIRED)
FIND_PACKAGE(Vorbis REQUIRED)
FIND_PACKAGE(Ogg REQUIRED)
# setup compiler options
SET(CXX_WARNS "-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-but-set-variable")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNS} -std=gnu++0x -pipe")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CXX_WARNS} -pipe")
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -ggdb")
SET(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O1 -ggdb")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O1 -ggdb")
SET(CMAKE_CXX_FLAGS_RELEASE "-Os -ffast-math")
SET(CMAKE_C_FLAGS_RELEASE "-Os -ffast-math")
SET(CMAKE_CXX_FLAGS_RELFORPERFORMANCE "-Ofast -mmmx -msse -msse2")
SET(CMAKE_C_FLAGS_RELFORPERFORMANCE "-Ofast -mmmx -msse -msse2")
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -static-libgcc -static-libstdc++ -Wl,--as-needed")
MESSAGE(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
ADD_DEFINITIONS(-D"BUILD_TYPE=\\\"${CMAKE_BUILD_TYPE}\\\"")
MESSAGE(STATUS "Build revision: ${BUILD_REVISION}")
ADD_DEFINITIONS(-D"BUILD_REVISION=\\\"${BUILD_REVISION}\\\"")
IF(USE_OPENGL_ES2)
MESSAGE(STATUS "Renderer: OpenGL ES 2.0")
ELSE()
MESSAGE(STATUS "Renderer: OpenGL")
ENDIF()
IF(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
MESSAGE(STATUS "Debug information: ON")
ADD_DEFINITIONS(-DDEBUG)
@ -189,8 +198,6 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl1.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painterogl2.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp
@ -205,6 +212,7 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/paintershadermanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/coordsbuffer.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
# framework sound
${CMAKE_CURRENT_LIST_DIR}/sound/soundsource.cpp

@ -0,0 +1,10 @@
# Try to find the OpenGLES2 librairy
# OPENGLES1_FOUND - system has OpenGL ES 1.0
# OPENGLES1_INCLUDE_DIR - the OpenGL ES 1.0 include directory
# OPENGLES1_LIBRARY - the OpenGL ES 1.0 library
FIND_PATH(OPENGLES1_INCLUDE_DIR NAMES GLES/gl.h)
FIND_LIBRARY(OPENGLES1_LIBRARY NAMES GLESv1_CM)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES2 DEFAULT_MSG OPENGLES1_LIBRARY OPENGLES1_INCLUDE_DIR)
MARK_AS_ADVANCED(OPENGLES1_LIBRARY OPENGLES1_INCLUDE_DIR)

@ -1,10 +1,10 @@
# Try to find the OpenGLES librairy
# OPENGLES_FOUND - system has OpenGLES
# OPENGLES_INCLUDE_DIR - the OpenGLES include directory
# OPENGLES_LIBRARY - the OpenGLES library
# Try to find the OpenGLES2 librairy
# OPENGLES2_FOUND - system has OpenGL ES 2.0
# OPENGLES2_INCLUDE_DIR - the OpenGL ES 2.0 include directory
# OPENGLES2_LIBRARY - the OpenGL ES 2.0 library
FIND_PATH(OPENGLES_INCLUDE_DIR NAMES GLES2/gl2.h)
FIND_LIBRARY(OPENGLES_LIBRARY NAMES GLESv2)
FIND_PATH(OPENGLES2_INCLUDE_DIR NAMES GLES2/gl2.h)
FIND_LIBRARY(OPENGLES2_LIBRARY NAMES GLESv2)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES DEFAULT_MSG OPENGLES_LIBRARY OPENGLES_INCLUDE_DIR)
MARK_AS_ADVANCED(OPENGLES_LIBRARY OPENGLES_INCLUDE_DIR)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR)
MARK_AS_ADVANCED(OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR)

@ -27,6 +27,7 @@
#include "glutil.h"
class Texture;
class Image;
class AnimatedTexture;
class Font;
class FrameBuffer;
@ -41,6 +42,7 @@ class ParticleSystem;
typedef std::weak_ptr<Texture> TextureWeakPtr;
typedef std::weak_ptr<ParticleSystem> ParticleSystemWeakPtr;
typedef std::shared_ptr<Image> ImagePtr;
typedef std::shared_ptr<Texture> TexturePtr;
typedef std::shared_ptr<AnimatedTexture> AnimatedTexturePtr;
typedef std::shared_ptr<Font> FontPtr;

@ -23,6 +23,7 @@
#include "font.h"
#include "texturemanager.h"
#include "graphics.h"
#include "image.h"
#include <framework/otml/otml.h>
@ -42,8 +43,9 @@ void Font::load(const OTMLNodePtr& fontNode)
if(OTMLNodePtr node = fontNode->get("fixed-glyph-width")) {
for(int glyph = m_firstGlyph; glyph < 256; ++glyph)
m_glyphsSize[glyph] = Size(node->value<int>(), m_glyphHeight);
} else
calculateGlyphsWidthsAutomatically(glyphSize);
} else {
calculateGlyphsWidthsAutomatically(Image::load(textureFile), glyphSize);
}
// new line actually has a size that will be useful in multiline algorithm
m_glyphsSize[(uchar)'\n'] = Size(1, m_glyphHeight);
@ -247,10 +249,10 @@ Size Font::calculateTextRectSize(const std::string& text)
return size;
}
void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
void Font::calculateGlyphsWidthsAutomatically(const ImagePtr& image, const Size& glyphSize)
{
int numHorizontalGlyphs = m_texture->getSize().width() / glyphSize.width();
auto texturePixels = m_texture->getPixels();
int numHorizontalGlyphs = image->getSize().width() / glyphSize.width();
auto texturePixels = image->getPixels();
// small AI to auto calculate pixels widths
for(int glyph = m_firstGlyph; glyph< 256; ++glyph) {
@ -266,7 +268,7 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
// check if all vertical pixels are alpha
for(int y = glyphCoords.top(); y <= glyphCoords.bottom(); ++y) {
if(texturePixels[(y * m_texture->getSize().width() * 4) + (x*4) + 3] != 0) {
if(texturePixels[(y * image->getSize().width() * 4) + (x*4) + 3] != 0) {
columnFilledPixels++;
foundAnything = true;
}

@ -64,7 +64,7 @@ public:
private:
/// Calculates each font character by inspecting font bitmap
void calculateGlyphsWidthsAutomatically(const Size& glyphSize);
void calculateGlyphsWidthsAutomatically(const ImagePtr& image, const Size& glyphSize);
std::string m_name;
int m_glyphHeight;

@ -26,7 +26,6 @@
#include <framework/platform/platformwindow.h>
uint FrameBuffer::boundFbo = 0;
std::vector<bool> auxBuffers;
FrameBuffer::FrameBuffer()
{
@ -41,42 +40,19 @@ FrameBuffer::FrameBuffer(const Size& size)
void FrameBuffer::internalCreate()
{
m_prevBoundFbo = 0;
m_fbo = 0;
if(g_graphics.canUseFBO()) {
glGenFramebuffers(1, &m_fbo);
if(!m_fbo)
logFatal("Unable to create framebuffer object");
}
#ifndef OPENGL_ES2
else { // use auxiliar buffers when FBOs are not supported
m_fbo = 0;
if(auxBuffers.size() == 0) {
int maxAuxs = 0;
glGetIntegerv(GL_AUX_BUFFERS, &maxAuxs);
auxBuffers.resize(maxAuxs+1, false);
}
for(uint i=1;i<auxBuffers.size();++i) {
if(auxBuffers[i] == false) {
m_fbo = i;
auxBuffers[i] = true;
break;
}
}
if(!m_fbo)
logFatal("There is no available auxiliar buffer for a new framebuffer, total AUXs: ", auxBuffers.size()-1);
}
#endif
}
FrameBuffer::~FrameBuffer()
{
if(g_graphics.canUseFBO()) {
if(m_fbo != 0)
glDeleteFramebuffers(1, &m_fbo);
}
#ifndef OPENGL_ES2
else {
auxBuffers[m_fbo] = false;
}
#endif
}
void FrameBuffer::resize(const Size& size)
@ -90,7 +66,7 @@ void FrameBuffer::resize(const Size& size)
m_texture = TexturePtr(new Texture(size.width(), size.height(), 4));
m_texture->setSmooth(true);
if(g_graphics.canUseFBO()) {
if(m_fbo) {
internalBind();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0);
@ -98,6 +74,8 @@ void FrameBuffer::resize(const Size& size)
if(status != GL_FRAMEBUFFER_COMPLETE)
logFatal("Unable to setup framebuffer object");
internalRelease();
} else {
m_screenBackup = TexturePtr(new Texture(size.width(), size.height(), 4));
}
}
@ -147,58 +125,43 @@ void FrameBuffer::draw(const Rect& dest)
void FrameBuffer::internalBind()
{
if(boundFbo == m_fbo)
return;
assert(boundFbo != m_fbo);
if(g_graphics.canUseFBO()) {
if(m_fbo) {
assert(boundFbo != m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
m_prevBoundFbo = boundFbo;
boundFbo = m_fbo;
} else {
// backup screen color buffer into a texture
m_screenBackup->bind();
Size size = getSize();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.width(), size.height());
}
#ifndef OPENGL_ES2
else {
int buffer = GL_AUX0 + m_fbo - 1;
glDrawBuffer(buffer);
glReadBuffer(buffer);
}
#endif
m_prevBoundFbo = boundFbo;
boundFbo = m_fbo;
}
void FrameBuffer::internalRelease()
{
assert(boundFbo == m_fbo);
if(g_graphics.canUseFBO()) {
if(m_fbo) {
assert(boundFbo == m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_prevBoundFbo);
}
#ifndef OPENGL_ES2
else {
m_texture->bind();
boundFbo = m_prevBoundFbo;
} else {
Size size = getSize();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.width(), size.height());
int buffer = GL_BACK;
if(m_prevBoundFbo != 0)
buffer = GL_AUX0 + m_fbo - 1;
// copy the drawn color buffer into the framebuffer texture
m_texture->bind();
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.width(), size.height());
glDrawBuffer(buffer);
glReadBuffer(buffer);
// restore screen original content
g_painter->drawTexturedRect(Rect(0, 0, size), m_screenBackup, Rect(0, 0, size));
}
#endif
boundFbo = m_prevBoundFbo;
}
Size FrameBuffer::getSize()
{
#ifndef OPENGL_ES2
if(!g_graphics.canUseFBO()) {
if(m_fbo == 0) {
// the buffer size is limited by the window size
return Size(std::min(m_texture->getWidth(), g_window.getWidth()),
std::min(m_texture->getHeight(), g_window.getHeight()));
}
#endif
return m_texture->getSize();
}

@ -24,12 +24,71 @@
#ifndef GLUTIL_H
#define GLUTIL_H
#ifndef OPENGL_ES2
#include <GLES2/gl2.h>
#if OPENGL_ES==2
#include <GLES2/gl2.h>
#elif OPENGL_ES==1
#include <GLES/gl.h>
// define OpenGL 2.0 API just to make compile, it wont actually be used
inline void glBindFramebuffer (GLenum target, GLuint framebuffer) { }
inline void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) { }
inline void glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { }
inline void glGenFramebuffers (GLsizei n, GLuint* framebuffers) { }
inline void glGenerateMipmap (GLenum target) { }
inline GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target) { return GL_NONE; }
inline GLuint glCreateShader (GLenum type) { return 0; }
inline void glDeleteShader (GLuint shader) { }
inline void glCompileShader (GLuint shader) { }
inline void glAttachShader (GLuint program, GLuint shader) { }
inline void glDetachShader (GLuint program, GLuint shader) { }
inline void glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length) { }
inline void glGetShaderiv (GLuint shader, GLenum pname, GLint* params) { }
inline void glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) { }
inline void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { }
inline void glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) { }
inline GLuint glCreateProgram (void) { return 0; }
inline void glDeleteProgram (GLuint program) { }
inline void glUseProgram (GLuint program) { }
inline void glValidateProgram (GLuint program) { }
inline void glLinkProgram (GLuint program) { }
inline void glGetProgramiv (GLuint program, GLenum pname, GLint* params) { }
inline void glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) { }
inline void glBindAttribLocation (GLuint program, GLuint index, const GLchar* name) { }
inline int glGetAttribLocation (GLuint program, const GLchar* name) { return 0; }
inline int glGetUniformLocation (GLuint program, const GLchar* name) { return 0; }
inline void glUniform1f (GLint location, GLfloat x) { }
inline void glUniform1fv (GLint location, GLsizei count, const GLfloat* v) { }
inline void glUniform1i (GLint location, GLint x) { }
inline void glUniform1iv (GLint location, GLsizei count, const GLint* v) { }
inline void glUniform2f (GLint location, GLfloat x, GLfloat y) { }
inline void glUniform2fv (GLint location, GLsizei count, const GLfloat* v) { }
inline void glUniform2i (GLint location, GLint x, GLint y) { }
inline void glUniform2iv (GLint location, GLsizei count, const GLint* v) { }
inline void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) { }
inline void glUniform3fv (GLint location, GLsizei count, const GLfloat* v) { }
inline void glUniform3i (GLint location, GLint x, GLint y, GLint z) { }
inline void glUniform3iv (GLint location, GLsizei count, const GLint* v) { }
inline void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { }
inline void glUniform4fv (GLint location, GLsizei count, const GLfloat* v) { }
inline void glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) { }
inline void glUniform4iv (GLint location, GLsizei count, const GLint* v) { }
inline void glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { }
inline void glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { }
inline void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { }
inline void glVertexAttrib1f (GLuint indx, GLfloat x) { }
inline void glVertexAttrib1fv (GLuint indx, const GLfloat* values) { }
inline void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) { }
inline void glVertexAttrib2fv (GLuint indx, const GLfloat* values) { }
inline void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) { }
inline void glVertexAttrib3fv (GLuint indx, const GLfloat* values) { }
inline void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { }
inline void glVertexAttrib4fv (GLuint indx, const GLfloat* values) { }
inline void glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) { }
#else
#define GLEW_STATIC
#include <GL/glew.h>
#else
#include <GLES2/gl2.h>
//#include <GLES2/gl2ext.h>
#endif
#endif

@ -21,8 +21,15 @@
*/
#include "fontmanager.h"
#if OPENGL_ES==2
#include "painterogl2.h"
#elif OPENGL_ES==1
#include "painterogl1.h"
#else
#include "painterogl1.h"
#include "painterogl2.h"
#endif
#include <framework/graphics/graphics.h>
#include <framework/graphics/texture.h>
@ -30,14 +37,10 @@
Graphics g_graphics;
void oglDebugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, void* userParam)
{
logWarning("OGL: ", message);
}
Graphics::Graphics()
{
m_maxTextureSize = -1;
m_selectedPainterEngine = Painter_Any;
}
void Graphics::init()
@ -45,18 +48,16 @@ void Graphics::init()
logInfo("GPU ", glGetString(GL_RENDERER));
logInfo("OpenGL ", glGetString(GL_VERSION));
#ifndef OPENGL_ES2
#if OPENGL_ES==2
g_painterOGL2 = new PainterOGL2;
#elif OPENGL_ES==1
g_painterOGL1 = new PainterOGL1;
#else
// init GL extensions
GLenum err = glewInit();
if(err != GLEW_OK)
logFatal("Unable to init GLEW: ", glewGetErrorString(err));
#ifdef DEBUG_OPENGL
if(GLEW_ARB_debug_output)
glDebugMessageCallbackARB(oglDebugCallback, NULL);
#endif
// overwrite framebuffer API if needed
if(GLEW_EXT_framebuffer_object && !GLEW_ARB_framebuffer_object) {
glGenFramebuffers = glGenFramebuffersEXT;
@ -73,8 +74,6 @@ void Graphics::init()
// opengl 2 is only supported in newer hardware
if(GLEW_VERSION_2_0)
g_painterOGL2 = new PainterOGL2;
#else
g_painterOGL2 = new PainterOGL2;
#endif
// determine max texture size
@ -84,9 +83,6 @@ void Graphics::init()
if(m_maxTextureSize == -1 || m_maxTextureSize > maxTextureSize)
m_maxTextureSize = maxTextureSize;
//glClear(GL_COLOR_BUFFER_BIT);
//m_prefferedPainterEngine = Painter_OpenGL1;
selectPainterEngine(m_prefferedPainterEngine);
m_emptyTexture = TexturePtr(new Texture);
@ -96,15 +92,19 @@ void Graphics::terminate()
{
g_fonts.releaseFonts();
if(g_painterOGL1) {
delete g_painterOGL1;
g_painterOGL1 = nullptr;
}
#ifdef PAINTER_OGL2
if(g_painterOGL2) {
delete g_painterOGL2;
g_painterOGL2 = nullptr;
}
#endif
#ifdef PAINTER_OGL1
if(g_painterOGL1) {
delete g_painterOGL1;
g_painterOGL1 = nullptr;
}
#endif
g_painter = nullptr;
@ -127,6 +127,8 @@ bool Graphics::parseOption(const std::string& option)
m_useHardwareBuffers = false;
else if(option == "-no-non-power-of-two-textures")
m_useNonPowerOfTwoTextures = false;
else if(option == "-no-clamp-to-edge")
m_useClampToEdge = false;
else if(option == "-opengl1")
m_prefferedPainterEngine = Painter_OpenGL1;
else if(option == "-opengl2")
@ -138,13 +140,26 @@ bool Graphics::parseOption(const std::string& option)
bool Graphics::selectPainterEngine(PainterEngine painterEngine)
{
bool found = false;
#ifdef PAINTER_OGL2
// always prefer OpenGL 2 over OpenGL 1
if(g_painterOGL2 && (painterEngine == Painter_OpenGL2 || painterEngine == Painter_Any))
if(!found && g_painterOGL2 && (painterEngine == Painter_OpenGL2 || painterEngine == Painter_Any)) {
m_selectedPainterEngine = Painter_OpenGL2;
g_painter = g_painterOGL2;
found = true;
}
#endif
#ifdef PAINTER_OGL1
// fallback to OpenGL 1 in older hardwares
else if(g_painterOGL1 && (painterEngine == Painter_OpenGL1 || painterEngine == Painter_Any))
if(!found && g_painterOGL1 && (painterEngine == Painter_OpenGL1 || painterEngine == Painter_Any)) {
m_selectedPainterEngine = Painter_OpenGL1;
g_painter = g_painterOGL1;
else
found = true;
}
#endif
if(!found)
logFatal("Neither OpenGL 1.0 nor OpenGL 2.0 painter engine is supported by your platform, "
"try updating your graphics drivers or your hardware and then run again.");
@ -158,14 +173,6 @@ bool Graphics::selectPainterEngine(PainterEngine painterEngine)
return getPainterEngine() == painterEngine;
}
Graphics::PainterEngine Graphics::getPainterEngine()
{
if(g_painter == g_painterOGL2)
return Painter_OpenGL2;
else
return Painter_OpenGL1;
}
void Graphics::resize(const Size& size)
{
setViewportSize(size);
@ -187,11 +194,15 @@ void Graphics::resize(const Size& size)
0.0f, -2.0f/size.height(), 0.0f,
-1.0f, 1.0f, 1.0f };
#ifdef PAINTER_OGL1
if(g_painterOGL1)
g_painterOGL1->setProjectionMatrix(projectionMatrix);
#endif
#ifdef PAINTER_OGL2
if(g_painterOGL2)
g_painterOGL2->setProjectionMatrix(projectionMatrix);
#endif
}
void Graphics::beginRender()
@ -212,43 +223,55 @@ void Graphics::setViewportSize(const Size& size)
bool Graphics::canUseDrawArrays()
{
#ifndef OPENGL_ES2
#ifdef OPENGL_ES
return true;
#else
// glDrawArrays is supported by OpenGL 1.1
if(!GLEW_VERSION_1_1)
return false;
#else
return false;
#endif
return m_useDrawArrays;
#endif
}
bool Graphics::canUseShaders()
{
#ifndef OPENGL_ES2
#if OPENGL_ES==2
return true;
#elif OPENGL_ES==1
return false;
#else
// fragment and vertex programs are supported by OpenGL 2.0
if(GLEW_ARB_vertex_program && GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
return true;
#else
return true;
#endif
return false;
#endif
}
bool Graphics::canUseFBO()
{
#ifndef OPENGL_ES2
#if OPENGL_ES==2
return m_useFBO;
#elif OPENGL_ES==1
return false;
#else
// FBOs are supported by OpenGL 3.0
// or by OpenGL 2.0 with EXT_framebuffer_object (most of the OpenGL 2.0 implementations have this extension)
if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object)
return false;
#endif
return m_useFBO;
#endif
}
bool Graphics::canUseBilinearFiltering()
{
// bilinear filtering is supported by any OpenGL implementation
return m_useBilinearFiltering;
}
bool Graphics::canUseHardwareBuffers()
{
#ifndef OPENGL_ES2
#ifndef OPENGL_ES
// vertex buffer objects is supported by OpenGL 1.5
if(!GLEW_ARB_vertex_buffer_object)
return false;
#endif
@ -257,24 +280,46 @@ bool Graphics::canUseHardwareBuffers()
bool Graphics::canUseNonPowerOfTwoTextures()
{
#ifndef OPENGL_ES2
#if OPENGL_ES==2
return m_useNonPowerOfTwoTextures;
#elif OPENGL_ES==1
return false;
#else
// power of two textures is supported by OpenGL 2.0
if(!GLEW_ARB_texture_non_power_of_two)
return false;
#endif
return m_useNonPowerOfTwoTextures;
#endif
}
bool Graphics::canUseMipmaps()
{
// mipmaps is supported by any OpenGL implementation
return m_useMipmaps;
}
bool Graphics::canUseHardwareMipmaps()
{
#ifndef OPENGL_ES2
// glGenerateMipmap is supported when framebuffers are too
#if OPENGL_ES==2
return m_useHardwareMipmaps;
#elif OPENGL_ES==1
return false;
#else
// glGenerateMipmap is supported when FBOs are
if(!GLEW_ARB_framebuffer_object || !GLEW_EXT_framebuffer_object)
return false;
#endif
return m_useHardwareMipmaps;
#endif
}
bool Graphics::canUseClampToEdge()
{
#ifdef OPENGL_ES
return m_useClampToEdge;
#else
// GL_CLAMP_TO_EDGE is present in OpenGL 1.2
if(!GLEW_VERSION_1_2)
return false;
return m_useClampToEdge;
#endif
}

@ -42,7 +42,6 @@ public:
bool parseOption(const std::string& option);
bool selectPainterEngine(PainterEngine painterEngine);
PainterEngine getPainterEngine();
void resize(const Size& size);
void beginRender();
@ -53,6 +52,7 @@ public:
int getMaxTextureSize() { return m_maxTextureSize; }
const Size& getViewportSize() { return m_viewportSize; }
TexturePtr& getEmptyTexture() { return m_emptyTexture; }
PainterEngine getPainterEngine() { return m_selectedPainterEngine; }
bool canUseDrawArrays();
bool canUseShaders();
@ -62,6 +62,7 @@ public:
bool canUseNonPowerOfTwoTextures();
bool canUseMipmaps();
bool canUseHardwareMipmaps();
bool canUseClampToEdge();
private:
Size m_viewportSize;
@ -75,7 +76,9 @@ private:
Boolean<true> m_useNonPowerOfTwoTextures;
Boolean<true> m_useMipmaps;
Boolean<true> m_useHardwareMipmaps;
Boolean<true> m_useClampToEdge;
PainterEngine m_prefferedPainterEngine;
PainterEngine m_selectedPainterEngine;
};
extern Graphics g_graphics;

@ -0,0 +1,64 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "image.h"
#include <framework/core/resourcemanager.h>
#include <framework/thirdparty/apngloader.h>
Image::Image(const Size& size, int bpp, uint8 *pixels)
{
m_size = size;
m_bpp = bpp;
m_pixels.resize(size.area() * bpp);
memcpy(&m_pixels[0], pixels, m_pixels.size());
}
ImagePtr Image::load(const std::string& file)
{
ImagePtr image;
try {
// currently only png images are supported
if(!boost::ends_with(file, ".png"))
Fw::throwException("image file format no supported");
// load image file data
image = loadPNG(file);
} catch(Exception& e) {
logError("unable to load image '", file, "': ", e.what());
}
return image;
}
ImagePtr Image::loadPNG(const std::string& file)
{
std::stringstream fin;
g_resources.loadFile(file, fin);
ImagePtr image;
apng_data apng;
if(load_apng(fin, &apng) == 0) {
image = ImagePtr(new Image(Size(apng.width, apng.height), apng.bpp, apng.pdata));
free_apng(&apng);
}
return image;
}

@ -0,0 +1,47 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef IMAGE_H
#define IMAGE_H
#include "declarations.h"
#include <framework/util/databuffer.h>
class Image
{
public:
Image(const Size& size, int bpp, uint8 *pixels);
static ImagePtr load(const std::string& file);
static ImagePtr loadPNG(const std::string& file);
const std::vector<uint8>& getPixels() { return m_pixels; }
const Size& getSize() { return m_size; }
int getBpp() { return m_bpp; }
private:
std::vector<uint8> m_pixels;
Size m_size;
int m_bpp;
};
#endif

@ -63,10 +63,13 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
return;
bool textured = coordsBuffer.getTextureCoordCount() != 0;
if(textured)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
if(textured != m_textureEnabled) {
if(textured)
glEnable(GL_TEXTURE_2D);
else
glDisable(GL_TEXTURE_2D);
m_textureEnabled = textured;
}
// use vertex arrays if possible, much faster
if(g_graphics.canUseDrawArrays()) {
@ -95,7 +98,9 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
// draw the element in coords buffers
glDrawArrays(drawMode, 0, vertexCount);
} else {
}
#ifndef OPENGL_ES
else {
int verticesSize = vertexCount*2;
float *vertices = coordsBuffer.getVertexArray();
float *texCoords = coordsBuffer.getTextureCoordArray();
@ -111,6 +116,7 @@ void PainterOGL1::drawCoords(CoordsBuffer& coordsBuffer, DrawMode drawMode)
}
glEnd();
}
#endif
}
void PainterOGL1::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture)

@ -23,6 +23,8 @@
#ifndef PAINTEROGL1_H
#define PAINTEROGL1_H
#define PAINTER_OGL1
#include "painter.h"
/**
@ -35,8 +37,8 @@ class PainterOGL1 : public Painter
{
public:
enum MatrixMode {
MatrixProjection = GL_PROJECTION,
MatrixTexture = GL_TEXTURE
MatrixProjection = 0x1701, //GL_PROJECTION
MatrixTexture = 0x1702, //GL_TEXTURE
};
PainterOGL1();
@ -66,6 +68,7 @@ private:
void updateGlTextureMatrix();
GLenum m_matrixMode;
Boolean<false> m_textureEnabled;
};
extern PainterOGL1 *g_painterOGL1;

@ -23,6 +23,8 @@
#ifndef PAINTEROGL2_H
#define PAINTEROGL2_H
#define PAINTER_OGL2
#include "painter.h"
/**

@ -1,67 +0,0 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
static const std::string glslMainVertexShader = "\n\
highp vec4 calculatePosition();\n\
void main() {\n\
gl_Position = calculatePosition();\n\
}\n";
static const std::string glslMainWithTexCoordsVertexShader = "\n\
attribute highp vec2 a_texCoord;\n\
uniform highp mat2 texTransformMatrix;\n\
varying highp vec2 texCoord;\n\
highp vec4 calculatePosition();\n\
void main()\n\
{\n\
gl_Position = calculatePosition();\n\
texCoord = texTransformMatrix * a_texCoord;\n\
}\n";
static std::string glslPositionOnlyVertexShader = "\n\
attribute highp vec2 a_vertex;\n\
uniform highp mat3 projectionMatrix;\n\
highp vec4 calculatePosition() {\n\
return vec4(projectionMatrix * vec3(a_vertex.xy, 1), 1);\n\
}\n";
static const std::string glslMainFragmentShader = "\n\
uniform lowp float opacity;\n\
lowp vec4 calculatePixel();\n\
void main()\n\
{\n\
gl_FragColor = calculatePixel() * opacity;\n\
}\n";
static const std::string glslTextureSrcFragmentShader = "\n\
varying mediump vec2 texCoord;\n\
uniform lowp vec4 color;\n\
uniform sampler2D tex0;\n\
lowp vec4 calculatePixel() {\n\
return texture2D(tex0, texCoord) * color;\n\
}\n";
static const std::string glslSolidColorFragmentShader = "\n\
uniform lowp vec4 color;\n\
lowp vec4 calculatePixel() {\n\
return color;\n\
}\n";

@ -46,7 +46,7 @@ Shader::~Shader()
bool Shader::compileSourceCode(const std::string& sourceCode)
{
#ifndef OPENGL_ES2
#ifndef OPENGL_ES
static const char *qualifierDefines =
"#define lowp\n"
"#define mediump\n"
@ -65,7 +65,7 @@ bool Shader::compileSourceCode(const std::string& sourceCode)
glShaderSource(m_shaderId, 1, &c_source, NULL);
glCompileShader(m_shaderId);
int res;
int res = GL_FALSE;
glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &res);
return (res == GL_TRUE);
}
@ -79,7 +79,7 @@ bool Shader::compileSourceFile(const std::string& sourceFile)
std::string Shader::log()
{
std::string infoLog;
GLint infoLogLength;
GLint infoLogLength = 0;
glGetShaderiv(m_shaderId, GL_INFO_LOG_LENGTH, &infoLogLength);
if(infoLogLength > 1) {
std::vector<char> buf(infoLogLength);

@ -87,7 +87,7 @@ bool ShaderProgram::link()
glLinkProgram(m_programId);
GLint value;
GLint value = GL_FALSE;
glGetProgramiv(m_programId, GL_LINK_STATUS, &value);
m_linked = (value != GL_FALSE);
@ -118,7 +118,7 @@ void ShaderProgram::release()
std::string ShaderProgram::log()
{
std::string infoLog;
GLint infoLogLength;
GLint infoLogLength = 0;
glGetProgramiv(m_programId, GL_INFO_LOG_LENGTH, &infoLogLength);
if(infoLogLength > 1) {
std::vector<char> buf(infoLogLength);

@ -32,7 +32,7 @@ Texture::Texture()
Texture::Texture(int width, int height, int channels, uchar *pixels)
{
// generate opengl texture
m_textureId = internalLoadGLTexture(pixels, channels, width, height);
internalLoadGLTexture(pixels, channels, width, height);
}
Texture::~Texture()
@ -66,7 +66,8 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
GLuint id;
glGenTextures(1, &id);
assert(id != 0);
glBindTexture(GL_TEXTURE_2D, id);
m_textureId = id;
bind();
// detect pixels GL format
GLenum format = 0;
@ -88,15 +89,25 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
// load pixels into gl memory
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.width(), m_size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
// disable texture border
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
GLint texParam = GL_REPEAT;
if(g_graphics.canUseClampToEdge())
texParam = GL_CLAMP_TO_EDGE; // disable texture borders by default
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
setupFilters();
return id;
}
void Texture::bind()
{
// must reset painter texture state
//g_painter->setTexture(this);
glBindTexture(GL_TEXTURE_2D, m_textureId);
}
void Texture::generateMipmaps()
{
if(!generateHardwareMipmaps()) {
@ -112,11 +123,6 @@ bool Texture::generateHardwareMipmaps()
if(!g_graphics.canUseHardwareMipmaps())
return false;
#ifndef OPENGL_ES2
if(!GLEW_ARB_framebuffer_object)
return false;
#endif
bind();
if(!m_hasMipmaps) {
@ -141,28 +147,6 @@ void Texture::setSmooth(bool smooth)
setupFilters();
}
std::vector<uint8> Texture::getPixels()
{
std::vector<uint8> pixels(m_size.area()*4, 0);
#ifdef OPENGL_ES2
// hack to copy pixels from opengl memory in opengl es
// NOTE: this can be slow, but its the only way to get pixels from a texture in OpenGL ES
FrameBufferPtr fb(new FrameBuffer(m_size));
fb->bind();
fb->clear(Color::alpha);
g_painter->saveAndResetState();
g_painter->drawTexturedRect(Rect(0,0,m_size), shared_from_this());
glReadPixels(0, 0, m_size.width(), m_size.height(), GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
g_painter->restoreSavedState();
fb->release();
#else
// copy pixels from opengl memory
glBindTexture(GL_TEXTURE_2D, m_textureId);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
#endif
return pixels;
}
void Texture::generateSoftwareMipmaps(std::vector<uint8> inPixels)
{
bind();

@ -32,7 +32,7 @@ public:
Texture(int width, int height, int channels, uchar* pixels = NULL);
virtual ~Texture();
void bind() { glBindTexture(GL_TEXTURE_2D, m_textureId); }
void bind();
/// Tries to generate mipmaps via hardware, otherwise fallback to software implementation
void generateMipmaps();
@ -43,10 +43,8 @@ public:
/// Activate texture anti-aliasing giving a better look when they are resized
void setSmooth(bool smooth);
GLuint getId() { return m_textureId; }
/// Return actual texture pixels
std::vector<uint8> getPixels();
GLuint getId() { return m_textureId; }
int getWidth() { return m_size.width(); }
int getHeight() { return m_size.height(); }

@ -41,14 +41,14 @@ X11Window::X11Window()
m_wmDelete = 0;
m_size = Size(600,480);
#ifndef OPENGL_ES2
m_fbConfig = 0;
m_glxContext = 0;
#else
#ifdef OPENGL_ES
m_eglConfig = 0;
m_eglContext = 0;
m_eglDisplay = 0;
m_eglSurface = 0;
#else
m_fbConfig = 0;
m_glxContext = 0;
#endif
m_keyMap[XK_Escape] = Fw::KeyEscape;
@ -350,27 +350,43 @@ bool X11Window::internalSetupWindowInput()
void X11Window::internalCheckGL()
{
#ifndef OPENGL_ES2
if(!glXQueryExtension(m_display, NULL, NULL))
logFatal("GLX not supported");
#else
#ifdef OPENGL_ES
m_eglDisplay = eglGetDisplay((EGLNativeDisplayType)m_display);
if(m_eglDisplay == EGL_NO_DISPLAY)
logFatal("EGL not supported");
if(!eglInitialize(m_eglDisplay, NULL, NULL))
logFatal("Unable to initialize EGL");
#else
if(!glXQueryExtension(m_display, NULL, NULL))
logFatal("GLX not supported");
#endif
}
void X11Window::internalChooseGLVisual()
{
#ifndef OPENGL_ES2
#ifdef OPENGL_ES
static int attrList[] = {
#if OPENGL_ES==2
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#else
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
#endif
EGL_NONE
};
EGLint numConfig;
if(!eglChooseConfig(m_eglDisplay, attrList, &m_eglConfig, 1, &numConfig))
logFatal("Failed to choose EGL config");
if(numConfig != 1)
logWarning("Didn't got the exact EGL config");
m_rootWindow = DefaultRootWindow(m_display);
#else
static int attrList[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, True,
//GLX_DEPTH_SIZE, 24,
//GLX_STENCIL_SIZE, 8,
None
};
@ -384,67 +400,38 @@ void X11Window::internalChooseGLVisual()
logFatal("Couldn't choose RGBA, double buffered visual");
m_rootWindow = RootWindow(m_display, m_visual->screen);
#else
static int attrList[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
//EGL_STENCIL_SIZE, 8,
EGL_NONE
};
EGLint numConfig;
if(!eglChooseConfig(m_eglDisplay, attrList, &m_eglConfig, 1, &numConfig))
logFatal("Failed to choose EGL config");
if(numConfig != 1)
logWarning("Didn't got the exact EGL config");
m_rootWindow = DefaultRootWindow(m_display);
#endif
}
void X11Window::internalCreateGLContext()
{
#ifndef OPENGL_ES2
#ifdef DEBUG_OPENGL
typedef GLXContext (*GLXCREATECONTEXTATTRIBSARBPROC)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = NULL;
glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddress((const GLubyte*) "glXCreateContextAttribsARB");
if(glXCreateContextAttribsARB) {
int attrs[] = {
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
None
};
m_glxContext = glXCreateContextAttribsARB(m_display, *m_fbConfig, NULL, True, attrs);
} else
#endif
m_glxContext = glXCreateContext(m_display, m_visual, NULL, True);
if(!m_glxContext)
logFatal("Unable to create GLX context");
if(!glXIsDirect(m_display, m_glxContext))
logWarning("GL direct rendering is not possible");
#else
#ifdef OPENGL_ES
EGLint attrList[] = {
#if OPENGL_ES==2
EGL_CONTEXT_CLIENT_VERSION, 2,
#else
EGL_CONTEXT_CLIENT_VERSION, 1,
#endif
EGL_NONE
};
m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, attrList);
if(m_eglContext == EGL_NO_CONTEXT )
logFatal("Unable to create EGL context: ", eglGetError());
#else
m_glxContext = glXCreateContext(m_display, m_visual, NULL, True);
if(!m_glxContext)
logFatal("Unable to create GLX context");
if(!glXIsDirect(m_display, m_glxContext))
logWarning("GL direct rendering is not possible");
#endif
}
void X11Window::internalDestroyGLContext()
{
#ifndef OPENGL_ES2
if(m_glxContext) {
glXMakeCurrent(m_display, None, NULL);
glXDestroyContext(m_display, m_glxContext);
m_glxContext = 0;
}
#else
#ifdef OPENGL_ES
if(m_eglDisplay) {
if(m_eglContext) {
eglDestroyContext(m_eglDisplay, m_eglContext);
@ -457,41 +444,48 @@ void X11Window::internalDestroyGLContext()
eglTerminate(m_eglDisplay);
m_eglDisplay = 0;
}
#else
if(m_glxContext) {
glXMakeCurrent(m_display, None, NULL);
glXDestroyContext(m_display, m_glxContext);
m_glxContext = 0;
}
#endif
}
void X11Window::internalConnectGLContext()
{
#ifndef OPENGL_ES2
if(!glXMakeCurrent(m_display, m_window, m_glxContext))
logFatal("Unable to set GLX context on X11 window");
#else
#ifdef OPENGL_ES
m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_window, NULL);
if(m_eglSurface == EGL_NO_SURFACE)
logFatal("Unable to create EGL surface: ", eglGetError());
if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext))
logFatal("Unable to connect EGL context into X11 window");
#else
if(!glXMakeCurrent(m_display, m_window, m_glxContext))
logFatal("Unable to set GLX context on X11 window");
#endif
}
void *X11Window::getExtensionProcAddress(const char *ext)
{
#ifndef OPENGL_ES2
return (void *)glXGetProcAddressARB((const GLubyte*)ext);
#else
#ifdef OPENGL_ES
//TODO
return NULL;
#else
return (void *)glXGetProcAddressARB((const GLubyte*)ext);
#endif
}
bool X11Window::isExtensionSupported(const char *ext)
{
#ifndef OPENGL_ES2
#ifdef OPENGL_ES
//TODO
return false;
#else
const char *exts = glXQueryExtensionsString(m_display, m_screen);
if(strstr(exts, ext))
return true;
#else
//TODO
#endif
return false;
}
@ -805,23 +799,11 @@ void X11Window::poll()
void X11Window::swapBuffers()
{
#if 0
auto now = std::chrono::high_resolution_clock::now();
auto gpuStart = now;
static decltype(now) cpuStart;
int cpu = std::chrono::duration_cast<std::chrono::nanoseconds>(now - cpuStart).count();
#endif
#ifndef OPENGL_ES2
#ifdef OPENGL_ES
eglSwapBuffers(m_eglDisplay, m_eglSurface);
#else
glFinish();
glXSwapBuffers(m_display, m_window);
#else
eglSwapBuffers(m_eglDisplay, m_eglSurface);
#endif
#if 0
now = std::chrono::high_resolution_clock::now();
int gpu = std::chrono::duration_cast<std::chrono::nanoseconds>(now - gpuStart).count();
cpuStart = now;
dump << "cpu" << cpu << "gpu" << gpu;
#endif
}
@ -956,7 +938,9 @@ void X11Window::setFullscreen(bool fullscreen)
void X11Window::setVerticalSync(bool enable)
{
#ifndef OPENGL_ES2
#ifdef OPENGL_ES
//TODO
#else
typedef GLint (*glSwapIntervalProc)(GLint);
glSwapIntervalProc glSwapInterval = NULL;
@ -967,8 +951,6 @@ void X11Window::setVerticalSync(bool enable)
if(glSwapInterval)
glSwapInterval(enable ? 1 : 0);
#else
//TODO
#endif
}
@ -1059,7 +1041,7 @@ std::string X11Window::getClipboardText()
std::string X11Window::getPlatformType()
{
#ifndef OPENGL_ES2
#ifndef OPENGL_ES
return "X11-GLX";
#else
return "X11-EGL";

@ -29,10 +29,10 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#ifndef OPENGL_ES2
#include <GL/glx.h>
#else
#ifdef OPENGL_ES
#include <EGL/egl.h>
#else
#include <GL/glx.h>
#endif
class X11Window : public PlatformWindow
@ -94,7 +94,7 @@ private:
Atom m_wmDelete;
std::string m_clipboardText;
#ifndef OPENGL_ES2
#ifndef OPENGL_ES
GLXContext m_glxContext;
GLXFBConfig *m_fbConfig;
#else

@ -184,27 +184,33 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
void Creature::drawOutfit(const Rect& destRect, bool resize)
{
static FrameBufferPtr outfitBuffer;
if(!outfitBuffer)
outfitBuffer = FrameBufferPtr(new FrameBuffer(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS)));
g_painter->saveAndResetState();
outfitBuffer->bind();
outfitBuffer->clear(Color::alpha);
internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South);
outfitBuffer->release();
g_painter->restoreSavedState();
if(resize) {
if(g_graphics.canUseFBO()) {
static FrameBufferPtr outfitBuffer;
if(!outfitBuffer)
outfitBuffer = FrameBufferPtr(new FrameBuffer(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS)));
g_painter->saveAndResetState();
outfitBuffer->bind();
outfitBuffer->clear(Color::alpha);
internalDrawOutfit(Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) + getDisplacement(), 1, false, true, Otc::South);
outfitBuffer->release();
g_painter->restoreSavedState();
Rect srcRect;
srcRect.resize(getExactSize(), getExactSize());
srcRect.moveBottomRight(Point(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS));
if(resize)
srcRect.resize(getExactSize(), getExactSize());
else
srcRect.resize(2*Otc::TILE_PIXELS*0.75f, 2*Otc::TILE_PIXELS*0.75f);
srcRect.moveBottomRight(Point(2*Otc::TILE_PIXELS - 1, 2*Otc::TILE_PIXELS - 1));
outfitBuffer->draw(destRect, srcRect);
} else {
Rect dest = destRect;
dest.expandTop(Otc::TILE_PIXELS);
dest.expandLeft(Otc::TILE_PIXELS);
outfitBuffer->draw(dest);
float scaleFactor;
if(resize)
scaleFactor = destRect.width() / (float)getExactSize();
else
scaleFactor = destRect.width() / (float)(2*Otc::TILE_PIXELS*0.75f);
Point dest = destRect.bottomRight() - (Point(Otc::TILE_PIXELS,Otc::TILE_PIXELS) - getDisplacement())*scaleFactor;
internalDrawOutfit(dest, scaleFactor, false, true, Otc::South);
}
}

Loading…
Cancel
Save