From f14706206a541ecc0d705c28321d3842e72358f0 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Fri, 20 Apr 2012 07:16:03 -0300 Subject: [PATCH] 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 --- CMakeLists.txt | 8 +- modules/game_outfit/outfit.otui | 2 +- src/framework/CMakeLists.txt | 82 +++++----- src/framework/cmake/FindOpenGLES1.cmake | 10 ++ src/framework/cmake/FindOpenGLES2.cmake | 16 +- src/framework/graphics/declarations.h | 2 + src/framework/graphics/font.cpp | 14 +- src/framework/graphics/font.h | 2 +- src/framework/graphics/framebuffer.cpp | 87 +++------- src/framework/graphics/glutil.h | 67 +++++++- src/framework/graphics/graphics.cpp | 143 +++++++++++------ src/framework/graphics/graphics.h | 5 +- src/framework/graphics/image.cpp | 64 ++++++++ src/framework/graphics/image.h | 47 ++++++ src/framework/graphics/painterogl1.cpp | 16 +- src/framework/graphics/painterogl1.h | 7 +- src/framework/graphics/painterogl2.h | 2 + src/framework/graphics/paintershadersources.h | 67 -------- src/framework/graphics/shader.cpp | 6 +- src/framework/graphics/shaderprogram.cpp | 4 +- src/framework/graphics/texture.cpp | 48 ++---- src/framework/graphics/texture.h | 6 +- src/framework/platform/x11window.cpp | 148 ++++++++---------- src/framework/platform/x11window.h | 8 +- src/otclient/core/creature.cpp | 42 ++--- 25 files changed, 510 insertions(+), 393 deletions(-) create mode 100644 src/framework/cmake/FindOpenGLES1.cmake create mode 100644 src/framework/graphics/image.cpp create mode 100644 src/framework/graphics/image.h delete mode 100644 src/framework/graphics/paintershadersources.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e6ebdc2..48f0769d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/modules/game_outfit/outfit.otui b/modules/game_outfit/outfit.otui index 3982eb73..6adb3441 100644 --- a/modules/game_outfit/outfit.otui +++ b/modules/game_outfit/outfit.otui @@ -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 diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index f3c47f25..e813c359 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -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 diff --git a/src/framework/cmake/FindOpenGLES1.cmake b/src/framework/cmake/FindOpenGLES1.cmake new file mode 100644 index 00000000..d8fc1475 --- /dev/null +++ b/src/framework/cmake/FindOpenGLES1.cmake @@ -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) \ No newline at end of file diff --git a/src/framework/cmake/FindOpenGLES2.cmake b/src/framework/cmake/FindOpenGLES2.cmake index 09692766..972c952f 100644 --- a/src/framework/cmake/FindOpenGLES2.cmake +++ b/src/framework/cmake/FindOpenGLES2.cmake @@ -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) \ No newline at end of file +FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES2 DEFAULT_MSG OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR) +MARK_AS_ADVANCED(OPENGLES2_LIBRARY OPENGLES2_INCLUDE_DIR) \ No newline at end of file diff --git a/src/framework/graphics/declarations.h b/src/framework/graphics/declarations.h index e2903c10..8434ed15 100644 --- a/src/framework/graphics/declarations.h +++ b/src/framework/graphics/declarations.h @@ -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 TextureWeakPtr; typedef std::weak_ptr ParticleSystemWeakPtr; +typedef std::shared_ptr ImagePtr; typedef std::shared_ptr TexturePtr; typedef std::shared_ptr AnimatedTexturePtr; typedef std::shared_ptr FontPtr; diff --git a/src/framework/graphics/font.cpp b/src/framework/graphics/font.cpp index 55dd3cda..8350fd0e 100644 --- a/src/framework/graphics/font.cpp +++ b/src/framework/graphics/font.cpp @@ -23,6 +23,7 @@ #include "font.h" #include "texturemanager.h" #include "graphics.h" +#include "image.h" #include @@ -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(), 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; } diff --git a/src/framework/graphics/font.h b/src/framework/graphics/font.h index ecec6f99..501a0cfe 100644 --- a/src/framework/graphics/font.h +++ b/src/framework/graphics/font.h @@ -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; diff --git a/src/framework/graphics/framebuffer.cpp b/src/framework/graphics/framebuffer.cpp index f3b40f6f..66a7e730 100644 --- a/src/framework/graphics/framebuffer.cpp +++ b/src/framework/graphics/framebuffer.cpp @@ -26,7 +26,6 @@ #include uint FrameBuffer::boundFbo = 0; -std::vector 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;isetSmooth(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(); } diff --git a/src/framework/graphics/glutil.h b/src/framework/graphics/glutil.h index d2e67941..5807315a 100644 --- a/src/framework/graphics/glutil.h +++ b/src/framework/graphics/glutil.h @@ -24,12 +24,71 @@ #ifndef GLUTIL_H #define GLUTIL_H -#ifndef OPENGL_ES2 +#include +#if OPENGL_ES==2 +#include +#elif OPENGL_ES==1 +#include + +// 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 -#else -#include -//#include #endif #endif diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 2f3ba8d8..a3748d02 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -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 #include @@ -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 } diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h index b7ceb6fc..1d5bf50d 100644 --- a/src/framework/graphics/graphics.h +++ b/src/framework/graphics/graphics.h @@ -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 m_useNonPowerOfTwoTextures; Boolean m_useMipmaps; Boolean m_useHardwareMipmaps; + Boolean m_useClampToEdge; PainterEngine m_prefferedPainterEngine; + PainterEngine m_selectedPainterEngine; }; extern Graphics g_graphics; diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp new file mode 100644 index 00000000..476a56e6 --- /dev/null +++ b/src/framework/graphics/image.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010-2012 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 +#include + +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; +} diff --git a/src/framework/graphics/image.h b/src/framework/graphics/image.h new file mode 100644 index 00000000..c2d2d495 --- /dev/null +++ b/src/framework/graphics/image.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010-2012 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 + +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& getPixels() { return m_pixels; } + const Size& getSize() { return m_size; } + int getBpp() { return m_bpp; } + +private: + std::vector m_pixels; + Size m_size; + int m_bpp; +}; + +#endif diff --git a/src/framework/graphics/painterogl1.cpp b/src/framework/graphics/painterogl1.cpp index 6c3b9fc2..ccfcf0a1 100644 --- a/src/framework/graphics/painterogl1.cpp +++ b/src/framework/graphics/painterogl1.cpp @@ -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) diff --git a/src/framework/graphics/painterogl1.h b/src/framework/graphics/painterogl1.h index eb98282d..028f7124 100644 --- a/src/framework/graphics/painterogl1.h +++ b/src/framework/graphics/painterogl1.h @@ -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 m_textureEnabled; }; extern PainterOGL1 *g_painterOGL1; diff --git a/src/framework/graphics/painterogl2.h b/src/framework/graphics/painterogl2.h index dddc0778..bee963dd 100644 --- a/src/framework/graphics/painterogl2.h +++ b/src/framework/graphics/painterogl2.h @@ -23,6 +23,8 @@ #ifndef PAINTEROGL2_H #define PAINTEROGL2_H +#define PAINTER_OGL2 + #include "painter.h" /** diff --git a/src/framework/graphics/paintershadersources.h b/src/framework/graphics/paintershadersources.h deleted file mode 100644 index f313fd8e..00000000 --- a/src/framework/graphics/paintershadersources.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2010-2012 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"; diff --git a/src/framework/graphics/shader.cpp b/src/framework/graphics/shader.cpp index 67b2af4a..d303ed0a 100644 --- a/src/framework/graphics/shader.cpp +++ b/src/framework/graphics/shader.cpp @@ -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 buf(infoLogLength); diff --git a/src/framework/graphics/shaderprogram.cpp b/src/framework/graphics/shaderprogram.cpp index abb1269a..a08e8d4d 100644 --- a/src/framework/graphics/shaderprogram.cpp +++ b/src/framework/graphics/shaderprogram.cpp @@ -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 buf(infoLogLength); diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index 12a5c455..bed397bb 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -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 Texture::getPixels() -{ - std::vector 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 inPixels) { bind(); diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index 391df007..26137a0c 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -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 getPixels(); + GLuint getId() { return m_textureId; } int getWidth() { return m_size.width(); } int getHeight() { return m_size.height(); } diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index 090e640c..7e972a06 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -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(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(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"; diff --git a/src/framework/platform/x11window.h b/src/framework/platform/x11window.h index 4647854a..e163f294 100644 --- a/src/framework/platform/x11window.h +++ b/src/framework/platform/x11window.h @@ -29,10 +29,10 @@ #include #include -#ifndef OPENGL_ES2 -#include -#else +#ifdef OPENGL_ES #include +#else +#include #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 diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 1974344d..345d1f8b 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -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); } }