diff --git a/Android.mk b/Android.mk index 5038523435..0cbd849ae8 100644 --- a/Android.mk +++ b/Android.mk @@ -38,6 +38,7 @@ LOCAL_SRC_FILES :=\ net/resolve.cpp \ profiler/profiler.cpp \ gfx_es2/glsl_program.cpp \ + gfx_es2/gl_state.cpp \ gfx_es2/draw_buffer.cpp.arm \ gfx_es2/vertex_format.cpp \ gfx_es2/fbo.cpp \ @@ -54,7 +55,7 @@ LOCAL_SRC_FILES :=\ util/random/perlin.cpp -LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -fsigned-char -fno-strict-aliasing +LOCAL_CFLAGS := -O2 -DGL_GLEXT_PROTOTYPES -DARM -DUSING_GLES2 -fsigned-char -fno-strict-aliasing LOCAL_CPPFLAGS := -fno-exceptions -fno-rtti -std=gnu++0x LOCAL_LDLIBS := -lz LOCAL_C_INCLUDES := $(LOCAL_PATH)/ext/libzip diff --git a/base/PCMain.cpp b/base/PCMain.cpp index df4529d253..ea0830e255 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -13,10 +13,10 @@ #include -#include "SDL/SDL.h" -#include "SDL/SDL_timer.h" -#include "SDL/SDL_audio.h" -#include "SDL/SDL_video.h" +#include "SDL.h" +#include "SDL_timer.h" +#include "SDL_audio.h" +#include "SDL_video.h" #include "base/display.h" #include "base/logging.h" diff --git a/base/logging.h b/base/logging.h index 9433babef5..cd16386e81 100644 --- a/base/logging.h +++ b/base/logging.h @@ -22,7 +22,7 @@ inline void Crash() { __asm { int 3 }; } #else -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(ARM) #undef Crash inline void Crash() { diff --git a/file/file_util.cpp b/file/file_util.cpp index 28dec171a0..29d42d08f4 100644 --- a/file/file_util.cpp +++ b/file/file_util.cpp @@ -17,7 +17,7 @@ #include "base/basictypes.h" #include "file/file_util.h" -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__APPLE__) #define stat64 stat #endif diff --git a/gfx/gl_common.h b/gfx/gl_common.h new file mode 100644 index 0000000000..d96fd0533b --- /dev/null +++ b/gfx/gl_common.h @@ -0,0 +1,22 @@ +#ifndef _GL_COMMON_H +#define _GL_COMMON_H + +#if defined(USING_GLES2) +#if defined(IOS) +#include +#include +typedef char GLchar; +#else +#include +#include +#endif +#else // OpenGL +#include +#if defined(__APPLE__) +#include +#else +#include +#endif +#endif + +#endif //_GL_COMMON_H diff --git a/gfx/gl_debug_log.cpp b/gfx/gl_debug_log.cpp index 324bf7e497..e895fd81e6 100644 --- a/gfx/gl_debug_log.cpp +++ b/gfx/gl_debug_log.cpp @@ -1,16 +1,4 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -typedef char GLchar; -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - +#include "gfx/gl_common.h" #include "base/logging.h" void glCheckzor(const char *file, int line) { @@ -20,7 +8,7 @@ void glCheckzor(const char *file, int line) { } } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #if 0 void log_callback(GLenum source, GLenum type, GLuint id, @@ -56,7 +44,7 @@ void log_callback(GLenum source, GLenum type, #endif void gl_log_enable() { -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #if 0 glEnable(DEBUG_OUTPUT_SYNCHRONOUS_ARB); // TODO: Look into disabling, for more perf glDebugMessageCallback(&log_callback, 0); diff --git a/gfx/gl_debug_log.h b/gfx/gl_debug_log.h index cb2cd12f7e..411f55668d 100644 --- a/gfx/gl_debug_log.h +++ b/gfx/gl_debug_log.h @@ -6,7 +6,7 @@ void gl_log_enable(); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) //#define DEBUG_OPENGL #endif diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 24e8079dfb..79b9736926 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -1,30 +1,19 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include #include -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #include "image/png_load.h" #include "ext/etcpack/etcdec.h" #endif #include "image/zim_load.h" #include "base/logging.h" -#include "texture.h" +#include "gfx/texture.h" #include "gfx/texture_gen.h" #include "gfx/gl_debug_log.h" #include "gfx/gl_lost_manager.h" +#include "gfx/gl_common.h" Texture::Texture() : id_(0) { register_gl_resource_holder(this); @@ -76,7 +65,7 @@ bool Texture::Load(const char *filename) { glBindTexture(GL_TEXTURE_2D, id_); if (bpp == 1) { -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(USING_GLES2) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); #else glTexImage2D(GL_TEXTURE_2D, 0, 1, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); @@ -118,7 +107,7 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0==memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { @@ -141,7 +130,7 @@ bool Texture::Load(const char *filename) { return false; } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) bool Texture::LoadPNG(const char *filename) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { @@ -184,7 +173,7 @@ bool Texture::LoadXOR() { } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { @@ -244,7 +233,7 @@ bool Texture::LoadZIM(const char *filename) { int data_h = height[l]; if (data_w < 4) data_w = 4; if (data_h < 4) data_h = 4; -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(USING_GLES2) int compressed_image_bytes = data_w * data_h / 2; glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); @@ -255,7 +244,7 @@ bool Texture::LoadZIM(const char *filename) { #endif } GL_CHECK(); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif } else { diff --git a/gfx/texture.h b/gfx/texture.h index 1823c49494..65479f76a8 100644 --- a/gfx/texture.h +++ b/gfx/texture.h @@ -14,7 +14,7 @@ public: ~Texture(); bool LoadZIM(const char *filename); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) bool LoadPNG(const char *filename); #endif bool LoadXOR(); // Loads a placeholder texture. diff --git a/gfx/texture_dx11.cpp b/gfx/texture_dx11.cpp index a6ef42a750..5737aba3ca 100644 --- a/gfx/texture_dx11.cpp +++ b/gfx/texture_dx11.cpp @@ -1,23 +1,18 @@ // WIP, please ignore - - - -#include "gfx/texture.h" - #include #include #include #include -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) #include "image/png_load.h" #include "ext/etcpack/etcdec.h" #endif #include "image/zim_load.h" #include "base/logging.h" -#include "texture.h" +#include "gfx/texture.h" #include "gfx/texture_gen.h" #include "gfx/gl_debug_log.h" #include "gfx/gl_lost_manager.h" @@ -98,7 +93,7 @@ bool Texture::Load(const char *filename) { const char *name = fn; if (zim && 0 == memcmp(name, "Media/textures/", strlen("Media/textures"))) name += strlen("Media/textures/"); len = strlen(name); - #if !defined(ANDROID) && !defined(BLACKBERRY) + #if !defined(USING_GLES2) if (!strcmp("png", &name[len-3]) || !strcmp("PNG", &name[len-3])) { if (!LoadPNG(fn)) { @@ -122,7 +117,7 @@ bool Texture::Load(const char *filename) { } #ifndef METRO -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) bool Texture::LoadPNG(const char *filename) { unsigned char *image_data; if (1 != pngLoad(filename, &width_, &height_, &image_data, false)) { @@ -176,7 +171,7 @@ bool Texture::LoadXOR() { } -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) // Allocates using new[], doesn't free. uint8_t *ETC1ToRGBA(uint8_t *etc1, int width, int height) { @@ -236,7 +231,7 @@ bool Texture::LoadZIM(const char *filename) { int data_h = height[l]; if (data_w < 4) data_w = 4; if (data_h < 4) data_h = 4; -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(USING_GLES2) int compressed_image_bytes = data_w * data_h / 2; glCompressedTexImage2D(GL_TEXTURE_2D, l, GL_ETC1_RGB8_OES, width[l], height[l], 0, compressed_image_bytes, image_data[l]); GL_CHECK(); @@ -247,7 +242,7 @@ bool Texture::LoadZIM(const char *filename) { #endif } GL_CHECK(); -#if !defined(ANDROID) && !defined(BLACKBERRY) +#if !defined(USING_GLES2) //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, num_levels - 2); #endif } else { diff --git a/gfx_es2/CMakeLists.txt b/gfx_es2/CMakeLists.txt index 43e11ef74d..e3a45b0a7f 100644 --- a/gfx_es2/CMakeLists.txt +++ b/gfx_es2/CMakeLists.txt @@ -2,6 +2,7 @@ set(SRCS draw_buffer.cpp fbo.cpp glsl_program.cpp + gl_state.cpp vertex_format.cpp) set(SRCS ${SRCS}) diff --git a/gfx_es2/draw_buffer.cpp b/gfx_es2/draw_buffer.cpp index 698ab346c5..59db3ec0f2 100644 --- a/gfx_es2/draw_buffer.cpp +++ b/gfx_es2/draw_buffer.cpp @@ -1,15 +1,3 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include @@ -18,8 +6,10 @@ #include "math/math_util.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/glsl_program.h" +#include "gfx_es2/gl_state.h" #include "gfx/texture_atlas.h" #include "gfx/gl_debug_log.h" +#include "gfx/gl_common.h" enum { // Enough? @@ -50,8 +40,8 @@ void DrawBuffer::Flush(const GLSLProgram *program, bool set_blend_state) { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); if (set_blend_state) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } glUniform1i(program->sampler0, 0); glEnableVertexAttribArray(program->a_position); @@ -357,23 +347,18 @@ void DrawBuffer::DrawText(int font, const char *text, float x, float y, Color co } void DrawBuffer::EnableBlend(bool enable) { - if (enable) - { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - glDisable(GL_BLEND); + glstate.blend.set(enable); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } void DrawBuffer::SetClipRect(float x, float y, float w, float h) { // Sigh, OpenGL is upside down. glScissor(x, dp_yres - y, w, h); - glEnable(GL_SCISSOR_TEST); + glstate.scissorTest.enable(); } void DrawBuffer::NoClip() { - glDisable(GL_SCISSOR_TEST); + glstate.scissorTest.disable(); } diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 95a1807716..8a0517e0c4 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -1,40 +1,70 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include +#include + +#include "base/logging.h" +#include "gfx_es2/fbo.h" +#include "gfx/gl_common.h" + +#if defined(USING_GLES2) #define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER #define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER #define GL_RGBA8 GL_RGBA #ifndef GL_DEPTH_COMPONENT24 #define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES #endif -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif #endif -#include "base/logging.h" -#include "gfx_es2/fbo.h" +// TODO: Breakout this GL extension checker in its own file. + +struct GLExtensions { + bool OES_depth24; + bool OES_packed_depth_stencil; + bool OES_depth_texture; +}; + +GLExtensions gl_extensions; + +void CheckExtensions() { + static bool done = false; + if (done) + return; + done = true; + + memset(&gl_extensions, 0, sizeof(gl_extensions)); + + const char *extString = (const char *)glGetString(GL_EXTENSIONS); + + gl_extensions.OES_packed_depth_stencil = strstr(extString, "GL_OES_packed_depth_stencil"); + gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24"); + gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture"); +} + + struct FBO { GLuint handle; GLuint color_texture; - GLuint z_stencil_buffer; + GLuint z_stencil_buffer; // Either this is set, or the two below. + GLuint z_buffer; + GLuint stencil_buffer; int width; int height; }; + +// On PC, we always use GL_DEPTH24_STENCIL8. +// On Android, we try to use what's available. + FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { + CheckExtensions(); + FBO *fbo = new FBO(); fbo->width = width; fbo->height = height; + + // Color texture is same everywhere glGenFramebuffers(1, &fbo->handle); glGenTextures(1, &fbo->color_texture); - glGenRenderbuffers(1, &fbo->z_stencil_buffer); // Create the surfaces. glBindTexture(GL_TEXTURE_2D, fbo->color_texture); @@ -42,15 +72,65 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // TODO: We could opt to only create 16-bit render targets on slow devices. For later. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + +#ifdef USING_GLES2 + if (gl_extensions.OES_packed_depth_stencil) { + ILOG("Creating FBO using DEPTH24_STENCIL8"); + // Standard method + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil combined + glGenRenderbuffers(1, &fbo->z_stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + + // Bind it all together + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + } else { + ILOG("Creating FBO using separate stencil"); + // TEGRA + fbo->z_stencil_buffer = 0; + // 16-bit Z, separate 8-bit stencil + glGenRenderbuffers(1, &fbo->z_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + + // 8-bit stencil buffer + glGenRenderbuffers(1, &fbo->stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + + // Bind it all together + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); + } +#else + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 24-bit Z, 8-bit stencil + glGenRenderbuffers(1, &fbo->z_stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); // Bind it all together glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); +#endif GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { @@ -58,7 +138,10 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil) { ILOG("Framebuffer verified complete."); break; case GL_FRAMEBUFFER_UNSUPPORTED: - ELOG("Framebuffer format not supported"); + ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); break; default: FLOG("Other framebuffer error: %i", status); diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index 648d255366..034a82dc57 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -9,6 +9,8 @@ struct FBO; // No mipmap support. // num_color_textures must be 1 for now. // you lose bound texture state. + +// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil); // These functions should be self explanatory. diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp new file mode 100644 index 0000000000..f46352bcf4 --- /dev/null +++ b/gfx_es2/gl_state.cpp @@ -0,0 +1,24 @@ +#include "gl_state.h" + +OpenGLState glstate; + +void OpenGLState::Initialize() { + if(initialized) return; + + Restore(); + + initialized = true; +} + +void OpenGLState::Restore() { + blend.restore(); + blendEquation.restore(); + blendFunc.restore(); + + cullFace.restore(); + cullFaceMode.restore(); + + depthTest.restore(); + depthRange.restore(); + depthFunc.restore(); +} \ No newline at end of file diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h new file mode 100644 index 0000000000..af0626a546 --- /dev/null +++ b/gfx_es2/gl_state.h @@ -0,0 +1,134 @@ +#pragma once + +#include +#include +#include "gfx/gl_common.h" + + +// OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, +// as GL state changes can be expensive on some hardware. +class OpenGLState +{ +private: + template + class BoolState { + bool _value; + public: + BoolState() : _value(init) {} + + inline void set(bool value) { + if(value && value != _value) { + _value = value; + glEnable(cap); + } + if(!value && value != _value) { + _value = value; + glDisable(cap); + } + } + inline void enable() { + set(true); + } + inline void disable() { + set(false); + } + operator bool() const { + return isset(); + } + inline bool isset() { + return _value; + } + void restore() { + if(_value) + glEnable(cap); + else + glDisable(cap); + } + }; + +#define STATE1(func, p1type, p1def) \ + class SavedState1_##func { \ + p1type p1; \ + public: \ + SavedState1_##func() : p1(p1def) {}; \ + void set(p1type newp1) { \ + if(newp1 != p1) { \ + p1 = newp1; \ + func(p1); \ + } \ + } \ + void restore() { \ + func(p1); \ + } \ + } + +#define STATE2(func, p1type, p2type, p1def, p2def) \ + class SavedState2_##func { \ + p1type p1; \ + p2type p2; \ + public: \ + SavedState2_##func() : p1(p1def), p2(p2def) {}; \ + inline void set(p1type newp1, p2type newp2) { \ + if(newp1 != p1 || newp2 != p2) { \ + p1 = newp1; \ + p2 = newp2; \ + func(p1, p2); \ + } \ + } \ + inline void restore() { \ + func(p1, p2); \ + } \ + } + +#define STATEFLOAT4(func, def) \ + class SavedState4_##func { \ + float p[4]; \ + public: \ + SavedState4_##func() { \ + for (int i = 0; i < 4; i++) {p[i] = def;} \ + }; \ + inline void set(const float v[4]) { \ + if(memcmp(p,v,sizeof(float)*4)) { \ + memcpy(p,v,sizeof(float)*4); \ + func(p[0], p[1], p[2], p[3]); \ + } \ + } \ + inline void restore() { \ + func(p[0], p[1], p[2], p[3]); \ + } \ + } + + bool initialized; + +public: + OpenGLState() : initialized(false) {} + void Initialize(); + void Restore(); + + BoolState blend; + STATE2(glBlendFunc, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFunc; + STATE1(glBlendEquation, GLenum, GL_FUNC_ADD) blendEquation; + STATEFLOAT4(glBlendColor, 1.0f) blendColor; + + BoolState scissorTest; + + BoolState cullFace; + STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode; + STATE1(glFrontFace, GLenum, GL_CCW) frontFace; + + BoolState depthTest; + STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc; + + STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite; + +#if defined(USING_GLES2) + STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange; +#else + STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange; +#endif +}; + +#undef STATE1 +#undef STATE2 + +extern OpenGLState glstate; diff --git a/gfx_es2/glsl_program.cpp b/gfx_es2/glsl_program.cpp index 2f7ecf8b1f..21483470a3 100644 --- a/gfx_es2/glsl_program.cpp +++ b/gfx_es2/glsl_program.cpp @@ -1,16 +1,3 @@ -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -typedef char GLchar; -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include @@ -19,7 +6,7 @@ typedef char GLchar; #include "base/logging.h" #include "file/vfs.h" -#include "gfx_es2/glsl_program.h" +#include "glsl_program.h" static std::set active_programs; @@ -37,7 +24,7 @@ bool CompileShader(const char *source, GLuint shader, const char *filename) { ELOG("Error in shader compilation of %s!\n", filename); ELOG("Info log: %s\n", infoLog); ELOG("Shader source:\n%s\n", (const char *)source); -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(ARM) exit(1); #endif return false; diff --git a/gfx_es2/glsl_program.h b/gfx_es2/glsl_program.h index 18fa819fc8..f2417d40a3 100644 --- a/gfx_es2/glsl_program.h +++ b/gfx_es2/glsl_program.h @@ -4,22 +4,11 @@ #ifndef _RENDER_UTIL #define _RENDER_UTIL -#if defined(ANDROID) || defined(BLACKBERRY) -#include -#include -#else -#include -#if defined(__APPLE__) -#include -#else -#include -#endif -#endif - #include #include #include "gfx/gl_lost_manager.h" +#include "gfx/gl_common.h" // Represent a compiled and linked vshader/fshader pair. // A just-constructed object is valid but cannot be used as a shader program, meaning that diff --git a/math/math_util.cpp b/math/math_util.cpp index 70ecede4da..bab216b95f 100644 --- a/math/math_util.cpp +++ b/math/math_util.cpp @@ -17,7 +17,7 @@ unsigned int GenerateRandomNumber() { #include -#if defined(ANDROID) || defined(BLACKBERRY) +#if defined(ARM) void EnableFZ() { diff --git a/native.vcxproj b/native.vcxproj index d488538e03..de6389110c 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -221,6 +221,7 @@ + @@ -310,6 +311,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index ddc4fc3429..ad1206c6d1 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -230,6 +230,9 @@ ext + + gfx + @@ -405,6 +408,12 @@ ext + + base + + + gfx + @@ -465,4 +474,4 @@ {4515306f-4664-46bf-a89b-abfec5520a15} - \ No newline at end of file + diff --git a/tools/atlastool/atlastool.vcxproj b/tools/atlastool/atlastool.vcxproj index e55f42a1f8..d7c6770cf8 100644 --- a/tools/atlastool/atlastool.vcxproj +++ b/tools/atlastool/atlastool.vcxproj @@ -96,7 +96,7 @@ {f761046e-6c38-4428-a5f1-38391a37bb34} - {e8b58922-9827-493d-81e0-4b6e6bd77171} + {C4DF647E-80EA-4111-A0A8-218B1B711E18} diff --git a/tools/zimtool/zimtool.vcxproj b/tools/zimtool/zimtool.vcxproj index da00f755ea..46dfd90a1a 100644 --- a/tools/zimtool/zimtool.vcxproj +++ b/tools/zimtool/zimtool.vcxproj @@ -94,7 +94,7 @@ {f761046e-6c38-4428-a5f1-38391a37bb34} - {e8b58922-9827-493d-81e0-4b6e6bd77171} + {C4DF647E-80EA-4111-A0A8-218B1B711E18} diff --git a/ui/ui_context.cpp b/ui/ui_context.cpp index f5fd58dd0a..f961713b5a 100644 --- a/ui/ui_context.cpp +++ b/ui/ui_context.cpp @@ -3,13 +3,14 @@ #include "gfx/texture.h" #include "gfx_es2/draw_buffer.h" #include "gfx_es2/glsl_program.h" +#include "gfx_es2/gl_state.h" void UIContext::Begin() { - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.blend.enable(); + glstate.blendFunc.set(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glstate.cullFace.disable(); + glstate.depthTest.disable(); if (uishader_) glsl_bind(uishader_); if (uitexture_)