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
This commit is contained in:
Eduardo Bart 2012-04-20 07:16:03 -03:00
parent 58d76e255d
commit f14706206a
25 changed files with 515 additions and 398 deletions

View File

@ -7,7 +7,7 @@ INCLUDE(src/otclient/CMakeLists.txt)
# functions map for reading backtraces # functions map for reading backtraces
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -Wl,-Map=otclient.map") 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) 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
TARGET_LINK_LIBRARIES(otclient ${framework_LIBRARIES}) TARGET_LINK_LIBRARIES(otclient ${framework_LIBRARIES})
IF(USE_PCH) IF(PCH)
FIND_PACKAGE(PCHSupport REQUIRED) FIND_PACKAGE(PCHSupport REQUIRED)
ADD_PRECOMPILED_HEADER(otclient ${CMAKE_CURRENT_SOURCE_DIR}/src/framework/pch.h) ADD_PRECOMPILED_HEADER(otclient ${CMAKE_CURRENT_SOURCE_DIR}/src/framework/pch.h)
MESSAGE(STATUS "Use precompiled header: ON") MESSAGE(STATUS "Use precompiled header: ON")
ELSEIF(USE_PCH) ELSE()
MESSAGE(STATUS "Use precompiled header: OFF") MESSAGE(STATUS "Use precompiled header: OFF")
ENDIF(USE_PCH) ENDIF()
# installation # installation
SET(DATA_INSTALL_DIR share/otclient) SET(DATA_INSTALL_DIR share/otclient)

View File

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

View File

@ -6,52 +6,16 @@ ENDIF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 6)
# add framework cmake modules # add framework cmake modules
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake;${CMAKE_MODULE_PATH}") 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) 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) 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 # set debug as default build type
IF(NOT CMAKE_BUILD_TYPE) IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo) SET(CMAKE_BUILD_TYPE RelWithDebInfo)
ENDIF() ENDIF()
# 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)
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})
ELSE()
FIND_PACKAGE(OpenGL REQUIRED)
FIND_PACKAGE(GLEW REQUIRED)
SET(OPENGL_LIBRARIES ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
ENDIF()
IF(LUAJIT)
FIND_PACKAGE(LuaJIT REQUIRED)
ELSE()
FIND_PACKAGE(Lua REQUIRED)
ENDIF()
FIND_PACKAGE(PhysFS REQUIRED)
FIND_PACKAGE(GMP REQUIRED)
FIND_PACKAGE(ZLIB REQUIRED)
FIND_PACKAGE(OpenAL REQUIRED)
FIND_PACKAGE(VorbisFile REQUIRED)
FIND_PACKAGE(Vorbis REQUIRED)
FIND_PACKAGE(Ogg REQUIRED)
# setup compiler options # setup compiler options
SET(CXX_WARNS "-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-but-set-variable") 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_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CXX_WARNS} -std=gnu++0x -pipe")
@ -72,12 +36,57 @@ ADD_DEFINITIONS(-D"BUILD_TYPE=\\\"${CMAKE_BUILD_TYPE}\\\"")
MESSAGE(STATUS "Build revision: ${BUILD_REVISION}") MESSAGE(STATUS "Build revision: ${BUILD_REVISION}")
ADD_DEFINITIONS(-D"BUILD_REVISION=\\\"${BUILD_REVISION}\\\"") ADD_DEFINITIONS(-D"BUILD_REVISION=\\\"${BUILD_REVISION}\\\"")
IF(USE_OPENGL_ES2) # find needed libraries
MESSAGE(STATUS "Renderer: OpenGL ES 2.0") IF(WIN32)
ELSE() SET(Boost_THREADAPI win32)
MESSAGE(STATUS "Renderer: OpenGL")
ENDIF() ENDIF()
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost COMPONENTS system REQUIRED)
IF(OPENGLES STREQUAL "2.0")
FIND_PACKAGE(OpenGLES2 REQUIRED)
FIND_PACKAGE(EGL REQUIRED)
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)
FIND_PACKAGE(ZLIB REQUIRED)
FIND_PACKAGE(OpenAL REQUIRED)
FIND_PACKAGE(VorbisFile REQUIRED)
FIND_PACKAGE(Vorbis REQUIRED)
FIND_PACKAGE(Ogg REQUIRED)
IF(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") IF(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
MESSAGE(STATUS "Debug information: ON") MESSAGE(STATUS "Debug information: ON")
@ -189,8 +198,6 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painter.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/texture.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.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/paintershaderprogram.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/paintershadermanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/paintershadermanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/coordsbuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/coordsbuffer.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
# framework sound # framework sound
${CMAKE_CURRENT_LIST_DIR}/sound/soundsource.cpp ${CMAKE_CURRENT_LIST_DIR}/sound/soundsource.cpp

View File

@ -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)

View File

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

View File

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

View File

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

View File

@ -64,7 +64,7 @@ public:
private: private:
/// Calculates each font character by inspecting font bitmap /// 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; std::string m_name;
int m_glyphHeight; int m_glyphHeight;

View File

@ -26,7 +26,6 @@
#include <framework/platform/platformwindow.h> #include <framework/platform/platformwindow.h>
uint FrameBuffer::boundFbo = 0; uint FrameBuffer::boundFbo = 0;
std::vector<bool> auxBuffers;
FrameBuffer::FrameBuffer() FrameBuffer::FrameBuffer()
{ {
@ -41,42 +40,19 @@ FrameBuffer::FrameBuffer(const Size& size)
void FrameBuffer::internalCreate() void FrameBuffer::internalCreate()
{ {
m_prevBoundFbo = 0;
m_fbo = 0;
if(g_graphics.canUseFBO()) { if(g_graphics.canUseFBO()) {
glGenFramebuffers(1, &m_fbo); glGenFramebuffers(1, &m_fbo);
if(!m_fbo) if(!m_fbo)
logFatal("Unable to create framebuffer object"); 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() FrameBuffer::~FrameBuffer()
{ {
if(g_graphics.canUseFBO()) { if(m_fbo != 0)
glDeleteFramebuffers(1, &m_fbo); glDeleteFramebuffers(1, &m_fbo);
}
#ifndef OPENGL_ES2
else {
auxBuffers[m_fbo] = false;
}
#endif
} }
void FrameBuffer::resize(const Size& size) 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 = TexturePtr(new Texture(size.width(), size.height(), 4));
m_texture->setSmooth(true); m_texture->setSmooth(true);
if(g_graphics.canUseFBO()) { if(m_fbo) {
internalBind(); internalBind();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0); 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) if(status != GL_FRAMEBUFFER_COMPLETE)
logFatal("Unable to setup framebuffer object"); logFatal("Unable to setup framebuffer object");
internalRelease(); 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() void FrameBuffer::internalBind()
{ {
if(boundFbo == m_fbo) if(m_fbo) {
return; assert(boundFbo != m_fbo);
assert(boundFbo != m_fbo);
if(g_graphics.canUseFBO()) {
glBindFramebuffer(GL_FRAMEBUFFER, 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() void FrameBuffer::internalRelease()
{ {
assert(boundFbo == m_fbo); if(m_fbo) {
if(g_graphics.canUseFBO()) { assert(boundFbo == m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_prevBoundFbo); glBindFramebuffer(GL_FRAMEBUFFER, m_prevBoundFbo);
} boundFbo = m_prevBoundFbo;
#ifndef OPENGL_ES2 } else {
else {
m_texture->bind();
Size size = getSize(); Size size = getSize();
// 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()); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.width(), size.height());
int buffer = GL_BACK; // restore screen original content
if(m_prevBoundFbo != 0) g_painter->drawTexturedRect(Rect(0, 0, size), m_screenBackup, Rect(0, 0, size));
buffer = GL_AUX0 + m_fbo - 1;
glDrawBuffer(buffer);
glReadBuffer(buffer);
} }
#endif
boundFbo = m_prevBoundFbo;
} }
Size FrameBuffer::getSize() Size FrameBuffer::getSize()
{ {
#ifndef OPENGL_ES2 if(m_fbo == 0) {
if(!g_graphics.canUseFBO()) {
// the buffer size is limited by the window size // the buffer size is limited by the window size
return Size(std::min(m_texture->getWidth(), g_window.getWidth()), return Size(std::min(m_texture->getWidth(), g_window.getWidth()),
std::min(m_texture->getHeight(), g_window.getHeight())); std::min(m_texture->getHeight(), g_window.getHeight()));
} }
#endif
return m_texture->getSize(); return m_texture->getSize();
} }

View File

@ -24,12 +24,71 @@
#ifndef GLUTIL_H #ifndef GLUTIL_H
#define 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 #define GLEW_STATIC
#include <GL/glew.h> #include <GL/glew.h>
#else
#include <GLES2/gl2.h>
//#include <GLES2/gl2ext.h>
#endif #endif
#endif #endif

View File

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

View File

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

View File

@ -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;
}

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -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";

View File

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

View File

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

View File

@ -32,7 +32,7 @@ Texture::Texture()
Texture::Texture(int width, int height, int channels, uchar *pixels) Texture::Texture(int width, int height, int channels, uchar *pixels)
{ {
// generate opengl texture // generate opengl texture
m_textureId = internalLoadGLTexture(pixels, channels, width, height); internalLoadGLTexture(pixels, channels, width, height);
} }
Texture::~Texture() Texture::~Texture()
@ -66,7 +66,8 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
GLuint id; GLuint id;
glGenTextures(1, &id); glGenTextures(1, &id);
assert(id != 0); assert(id != 0);
glBindTexture(GL_TEXTURE_2D, id); m_textureId = id;
bind();
// detect pixels GL format // detect pixels GL format
GLenum format = 0; GLenum format = 0;
@ -88,15 +89,25 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
// load pixels into gl memory // load pixels into gl memory
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.width(), m_size.height(), 0, format, GL_UNSIGNED_BYTE, pixels); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_size.width(), m_size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
// disable texture border GLint texParam = GL_REPEAT;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); if(g_graphics.canUseClampToEdge())
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 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(); setupFilters();
return id; return id;
} }
void Texture::bind()
{
// must reset painter texture state
//g_painter->setTexture(this);
glBindTexture(GL_TEXTURE_2D, m_textureId);
}
void Texture::generateMipmaps() void Texture::generateMipmaps()
{ {
if(!generateHardwareMipmaps()) { if(!generateHardwareMipmaps()) {
@ -112,11 +123,6 @@ bool Texture::generateHardwareMipmaps()
if(!g_graphics.canUseHardwareMipmaps()) if(!g_graphics.canUseHardwareMipmaps())
return false; return false;
#ifndef OPENGL_ES2
if(!GLEW_ARB_framebuffer_object)
return false;
#endif
bind(); bind();
if(!m_hasMipmaps) { if(!m_hasMipmaps) {
@ -141,28 +147,6 @@ void Texture::setSmooth(bool smooth)
setupFilters(); 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) void Texture::generateSoftwareMipmaps(std::vector<uint8> inPixels)
{ {
bind(); bind();

View File

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

View File

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

View File

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

View File

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