Merge pull request #288 from hrydgard/move-glstate

Move glstate out to PPSSPP
This commit is contained in:
Henrik Rydgård 2015-09-06 16:58:05 +02:00
commit 9ce1822a83
19 changed files with 450 additions and 1231 deletions

View File

@ -79,12 +79,10 @@ LOCAL_SRC_FILES :=\
thread/threadpool.cpp \
gfx_es2/glsl_program.cpp \
gfx_es2/gpu_features.cpp \
gfx_es2/gl_state.cpp.arm \
gfx_es2/gl3stub.c \
gfx_es2/draw_buffer.cpp.arm \
gfx_es2/draw_text.cpp.arm \
gfx_es2/vertex_format.cpp \
gfx_es2/fbo.cpp \
gfx/gl_debug_log.cpp \
gfx/gl_lost_manager.cpp \
gfx/texture.cpp \

View File

@ -26,7 +26,7 @@
#include "math/math_util.h"
#include "net/resolve.h"
#include "android/native_audio.h"
#include "gfx_es2/gl_state.h"
#include "gfx/gl_common.h"
#include "app-android.h"
@ -364,8 +364,8 @@ extern "C" void Java_com_henrikrydgard_libnative_NativeRenderer_displayRender(JN
} else {
ELOG("BAD: Ended up in nativeRender even though app has quit.%s", "");
// Shouldn't really get here. Let's draw magenta.
glstate.depthWrite.set(GL_TRUE);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(1.0, 0.0, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}

View File

@ -29,7 +29,8 @@ SDLJoystick *joystick = NULL;
#include "base/display.h"
#include "base/logging.h"
#include "base/timeutil.h"
#include "gfx_es2/gl_state.h"
#include "gfx/gl_common.h"
#include "gfx_es2/gpu_features.h"
#include "input/input_state.h"
#include "input/keycodes.h"
#include "net/resolve.h"

View File

@ -22,7 +22,7 @@ QTM_USE_NAMESPACE
#include "base/logging.h"
#include "base/timeutil.h"
#include "file/zip_read.h"
#include "gfx_es2/gl_state.h"
#include "gfx/gl_common.h"
#include "input/input_state.h"
#include "input/keycodes.h"
#include "base/NativeApp.h"

View File

@ -3,7 +3,8 @@
#include "base/timeutil.h"
// For NV time functions. Ugly!
#include "gfx_es2/gl_state.h"
#include "gfx/gl_common.h"
#include "gfx_es2/gpu_features.h"
#ifdef _WIN32
#include <windows.h>

View File

@ -25,3 +25,75 @@ typedef char GLchar;
#include "../gfx_es2/gl3stub.h"
#endif
#ifdef USING_GLES2
#ifndef GL_MIN_EXT
#define GL_MIN_EXT 0x8007
#endif
#ifndef GL_MAX_EXT
#define GL_MAX_EXT 0x8008
#endif
#if defined(ANDROID) || defined(BLACKBERRY)
#include <EGL/egl.h>
// Additional extensions not included in GLES2/gl2ext.h from the NDK
typedef uint64_t EGLuint64NV;
typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
typedef EGLuint64NV(EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
extern PFNGLMAPBUFFERPROC glMapBuffer;
typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV;
typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum
srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName,
GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei
width, GLsizei height, GLsizei depth);
extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV;
#ifndef ARM64
typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (
GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1,
GLint mask, GLenum filter);
#endif
extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV;
extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
// Rename standard functions to the OES version.
#define glGenVertexArrays glGenVertexArraysOES
#define glBindVertexArray glBindVertexArrayOES
#define glDeleteVertexArrays glDeleteVertexArraysOES
#define glIsVertexArray glIsVertexArrayOES
#endif
#if !defined(BLACKBERRY)
#ifndef GL_READ_FRAMEBUFFER
#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER
#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER
#endif
#ifndef GL_DEPTH_COMPONENT24
#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
#endif
#endif
#ifndef GL_RGBA8
#define GL_RGBA8 GL_RGBA
#endif
#endif /* EGL_NV_system_time */
#ifndef GL_DEPTH24_STENCIL8_OES
#define GL_DEPTH24_STENCIL8_OES 0x88F0
#endif

View File

@ -12,7 +12,7 @@
#include "gfx/gl_debug_log.h"
#include "gfx/gl_lost_manager.h"
#include "gfx/gl_common.h"
#include "gfx_es2/gl_state.h"
#include "gfx_es2/gpu_features.h"
Texture::Texture() : id_(0) {
CheckGLExtensions();

View File

@ -6,13 +6,12 @@
#include "base/display.h"
#include "base/logging.h"
#include "math/math_util.h"
#include "gfx_es2/draw_buffer.h"
#include "gfx_es2/draw_text.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"
#include "gfx_es2/draw_buffer.h"
#include "gfx_es2/draw_text.h"
#include "gfx_es2/glsl_program.h"
#include "util/text/utf8.h"
enum {

View File

@ -12,9 +12,6 @@
#include "base/basictypes.h"
#include "gfx_es2/draw_buffer.h"
#if !(defined(_WIN32) && !defined(USING_QT_UI))
#include "gfx_es2/gl_state.h"
#endif
class Thin3DContext;
class Thin3DTexture;

View File

@ -1,413 +0,0 @@
#include <string.h>
#include "base/logging.h"
#include "gfx/gl_common.h"
#include "gfx_es2/fbo.h"
#include "gfx/gl_common.h"
#include "gfx_es2/gl_state.h"
#ifdef IOS
extern void bindDefaultFBO();
#endif
struct FBO {
GLuint handle;
GLuint color_texture;
GLuint z_stencil_buffer; // Either this is set, or the two below.
GLuint z_buffer;
GLuint stencil_buffer;
int width;
int height;
FBOColorDepth colorDepth;
bool native_fbo;
};
static FBO *g_overriddenBackbuffer;
static GLuint currentDrawHandle_ = 0;
static GLuint currentReadHandle_ = 0;
// On PC, we always use GL_DEPTH24_STENCIL8.
// On Android, we try to use what's available.
#ifndef USING_GLES2
FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) {
FBO *fbo = new FBO();
fbo->native_fbo = false;
fbo->width = width;
fbo->height = height;
fbo->colorDepth = colorDepth;
// Color texture is same everywhere
glGenFramebuffersEXT(1, &fbo->handle);
glGenTextures(1, &fbo->color_texture);
// Create the surfaces.
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
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);
// TODO: We could opt to only create 16-bit render targets on slow devices. For later.
switch (colorDepth) {
case FBO_8888:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
break;
case FBO_4444:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL);
break;
case FBO_5551:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL);
break;
case FBO_565:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
break;
}
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);
fbo->stencil_buffer = 0;
fbo->z_buffer = 0;
// 24-bit Z, 8-bit stencil
glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, width, height);
//glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height);
// Bind it all together
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
// ILOG("Framebuffer verified complete.");
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
ELOG("GL_FRAMEBUFFER_UNSUPPORTED");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ");
break;
default:
FLOG("Other framebuffer error: %i", status);
break;
}
// Unbind state we don't need
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
currentDrawHandle_ = fbo->handle;
currentReadHandle_ = fbo->handle;
return fbo;
}
#endif
int fbo_check_framebuffer_status(FBO *fbo) {
GLenum fbStatus;
#ifndef USING_GLES2
if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) {
fbStatus = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER);
} else if (gl_extensions.ARB_framebuffer_object) {
fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
} else {
fbStatus = 0;
}
#else
fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER);
#endif
return (int)fbStatus;
}
FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) {
CheckGLExtensions();
#ifndef USING_GLES2
if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) {
return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth);
} else if (!gl_extensions.ARB_framebuffer_object) {
return nullptr;
}
// If GLES2, we have basic FBO support and can just proceed.
#endif
FBO *fbo = new FBO();
fbo->native_fbo = false;
fbo->width = width;
fbo->height = height;
fbo->colorDepth = colorDepth;
// Color texture is same everywhere
glGenFramebuffers(1, &fbo->handle);
glGenTextures(1, &fbo->color_texture);
// Create the surfaces.
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
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);
// TODO: We could opt to only create 16-bit render targets on slow devices. For later.
switch (colorDepth) {
case FBO_8888:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
break;
case FBO_4444:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL);
break;
case FBO_5551:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL);
break;
case FBO_565:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
break;
}
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);
if (gl_extensions.IsGLES) {
if (gl_extensions.OES_packed_depth_stencil) {
ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height);
// 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_FRAMEBUFFER, fbo->handle);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
} else {
ILOG("Creating %i x %i FBO using separate stencil", width, height);
// TEGRA
fbo->z_stencil_buffer = 0;
// 16/24-bit Z, separate 8-bit stencil
glGenRenderbuffers(1, &fbo->z_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer);
glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : 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_FRAMEBUFFER, fbo->handle);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer);
glFramebufferRenderbuffer(GL_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_DEPTH24_STENCIL8, width, height);
// Bind it all together
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE:
// ILOG("Framebuffer verified complete.");
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
ELOG("GL_FRAMEBUFFER_UNSUPPORTED");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ");
break;
default:
FLOG("Other framebuffer error: %i", status);
break;
}
// Unbind state we don't need
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
currentDrawHandle_ = fbo->handle;
currentReadHandle_ = fbo->handle;
return fbo;
}
FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo)
{
if (!fbo)
fbo = new FBO();
fbo->native_fbo = true;
fbo->handle = native_fbo;
fbo->color_texture = 0;
fbo->z_stencil_buffer = 0;
fbo->z_buffer = 0;
fbo->stencil_buffer = 0;
fbo->width = 0;
fbo->height = 0;
fbo->colorDepth = FBO_8888;
return fbo;
}
static GLenum fbo_get_fb_target(bool read, GLuint **cached) {
bool supportsBlit = gl_extensions.ARB_framebuffer_object;
if (gl_extensions.IsGLES) {
supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit);
}
// Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV.
if (supportsBlit) {
if (read) {
*cached = &currentReadHandle_;
return GL_READ_FRAMEBUFFER;
} else {
*cached = &currentDrawHandle_;
return GL_DRAW_FRAMEBUFFER;
}
} else {
*cached = &currentDrawHandle_;
return GL_FRAMEBUFFER;
}
}
static void fbo_bind_fb_target(bool read, GLuint name) {
GLuint *cached;
GLenum target = fbo_get_fb_target(read, &cached);
if (*cached != name) {
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
glBindFramebuffer(target, name);
} else {
#ifndef USING_GLES2
glBindFramebufferEXT(target, name);
#endif
}
*cached = name;
}
}
void fbo_unbind() {
if (g_overriddenBackbuffer) {
fbo_bind_as_render_target(g_overriddenBackbuffer);
return;
}
CheckGLExtensions();
#ifndef USING_GLES2
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
} else if (gl_extensions.EXT_framebuffer_object) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
#ifdef IOS
bindDefaultFBO();
#endif
currentDrawHandle_ = 0;
currentReadHandle_ = 0;
}
void fbo_override_backbuffer(FBO *fbo) {
g_overriddenBackbuffer = fbo;
}
void fbo_bind_as_render_target(FBO *fbo) {
// Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing
// in ES 2.0 that actually separate them anyway of course, so doesn't matter.
fbo_bind_fb_target(false, fbo->handle);
// Always restore viewport after render target binding
glstate.viewport.restore();
}
void fbo_unbind_render_target() {
fbo_unbind();
}
// For GL_EXT_FRAMEBUFFER_BLIT and similar.
void fbo_bind_for_read(FBO *fbo) {
fbo_bind_fb_target(true, fbo->handle);
}
void fbo_unbind_read() {
fbo_bind_fb_target(true, 0);
}
void fbo_bind_color_as_texture(FBO *fbo, int color) {
if (fbo) {
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
}
}
void fbo_destroy(FBO *fbo) {
if (fbo->native_fbo) {
delete fbo;
return;
}
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &fbo->handle);
glDeleteRenderbuffers(1, &fbo->z_stencil_buffer);
glDeleteRenderbuffers(1, &fbo->z_buffer);
glDeleteRenderbuffers(1, &fbo->stencil_buffer);
} else if (gl_extensions.EXT_framebuffer_object) {
#ifndef USING_GLES2
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &fbo->handle);
glDeleteRenderbuffersEXT(1, &fbo->z_stencil_buffer);
#endif
}
currentDrawHandle_ = 0;
currentReadHandle_ = 0;
glDeleteTextures(1, &fbo->color_texture);
delete fbo;
}
void fbo_get_dimensions(FBO *fbo, int *w, int *h) {
*w = fbo->width;
*h = fbo->height;
}
int fbo_get_color_texture(FBO *fbo) {
return fbo->color_texture;
}
int fbo_get_depth_buffer(FBO *fbo) {
return fbo->z_buffer;
}
int fbo_get_stencil_buffer(FBO *fbo) {
return fbo->stencil_buffer;
}

View File

@ -1,49 +0,0 @@
#pragma once
// Simple wrapper around FBO functionality.
// Very C-ish API because that's what I felt like, and it's cool to completely
// hide the data from callers...
#include "gfx/gl_common.h"
struct FBO;
enum FBOColorDepth {
FBO_8888,
FBO_565,
FBO_4444,
FBO_5551,
};
// Creates a simple FBO with a RGBA32 color buffer stored in a texture, and
// optionally an accompanying Z/stencil buffer.
// 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, FBOColorDepth colorDepth = FBO_8888);
// Create an opaque FBO from a native GL FBO, optionally reusing an existing FBO structure.
// Useful for overriding the backbuffer FBO that is generated outside of this wrapper.
FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo = NULL);
int fbo_check_framebuffer_status(FBO *fbo);
// These functions should be self explanatory.
void fbo_bind_as_render_target(FBO *fbo);
// color must be 0, for now.
void fbo_bind_color_as_texture(FBO *fbo, int color);
void fbo_bind_for_read(FBO *fbo);
void fbo_unbind();
void fbo_unbind_render_target();
void fbo_unbind_read();
void fbo_destroy(FBO *fbo);
void fbo_get_dimensions(FBO *fbo, int *w, int *h);
int fbo_get_color_texture(FBO *fbo);
int fbo_get_depth_buffer(FBO *fbo);
int fbo_get_stencil_buffer(FBO *fbo);
void fbo_override_backbuffer(FBO *fbo); // Makes unbind bind this instead of the real backbuffer.

View File

@ -1,382 +0,0 @@
#include <stdlib.h>
#include "base/logging.h"
#include "base/stringutil.h"
#include "base/NativeApp.h"
#include "gl_state.h"
#ifdef _WIN32
#include "GL/wglew.h"
#endif
#if defined(USING_GLES2)
#if defined(ANDROID) || defined(BLACKBERRY)
PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
PFNGLDRAWTEXTURENVPROC glDrawTextureNV;
PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV;
PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV;
PFNGLMAPBUFFERPROC glMapBuffer;
PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
#endif
#ifndef IOS
#include "EGL/egl.h"
#endif
#endif
OpenGLState glstate;
GLExtensions gl_extensions;
std::string g_all_gl_extensions;
std::string g_all_egl_extensions;
int OpenGLState::state_count = 0;
void OpenGLState::Initialize() {
if (initialized)
return;
initialized = true;
Restore();
}
void OpenGLState::Restore() {
int count = 0;
blend.restore(); count++;
blendEquationSeparate.restore(); count++;
blendFuncSeparate.restore(); count++;
blendColor.restore(); count++;
scissorTest.restore(); count++;
scissorRect.restore(); count++;
cullFace.restore(); count++;
cullFaceMode.restore(); count++;
frontFace.restore(); count++;
depthTest.restore(); count++;
depthRange.restore(); count++;
depthFunc.restore(); count++;
depthWrite.restore(); count++;
colorMask.restore(); count++;
viewport.restore(); count++;
stencilTest.restore(); count++;
stencilOp.restore(); count++;
stencilFunc.restore(); count++;
stencilMask.restore(); count++;
dither.restore(); count++;
#if !defined(USING_GLES2)
colorLogicOp.restore(); count++;
logicOp.restore(); count++;
#endif
arrayBuffer.restore(); count++;
elementArrayBuffer.restore(); count++;
if (count != state_count) {
FLOG("OpenGLState::Restore is missing some states");
}
}
// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array
void CheckGLExtensions() {
// Make sure to only do this once. It's okay to call CheckGLExtensions from wherever.
static bool done = false;
if (done)
return;
done = true;
memset(&gl_extensions, 0, sizeof(gl_extensions));
#ifdef USING_GLES2
gl_extensions.IsGLES = true;
#endif
const char *renderer = (const char *)glGetString(GL_RENDERER);
const char *versionStr = (const char *)glGetString(GL_VERSION);
const char *glslVersionStr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
// Check vendor string to try and guess GPU
const char *cvendor = (char *)glGetString(GL_VENDOR);
// TODO: move this stuff to gpu_features.cpp
if (cvendor) {
const std::string vendor = StripSpaces(std::string(cvendor));
if (vendor == "NVIDIA Corporation"
|| vendor == "Nouveau"
|| vendor == "nouveau") {
gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA;
} else if (vendor == "Advanced Micro Devices, Inc."
|| vendor == "ATI Technologies Inc.") {
gl_extensions.gpuVendor = GPU_VENDOR_AMD;
} else if (vendor == "Intel"
|| vendor == "Intel Inc."
|| vendor == "Intel Corporation"
|| vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel
gl_extensions.gpuVendor = GPU_VENDOR_INTEL;
} else if (vendor == "ARM") {
gl_extensions.gpuVendor = GPU_VENDOR_ARM;
} else if (vendor == "Imagination Technologies") {
gl_extensions.gpuVendor = GPU_VENDOR_POWERVR;
} else if (vendor == "Qualcomm") {
gl_extensions.gpuVendor = GPU_VENDOR_ADRENO;
} else if (vendor == "Broadcom") {
gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM;
// Just for reference: Galaxy Y has renderer == "VideoCore IV HW"
} else {
gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
}
} else {
gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
}
ILOG("GPU Vendor : %s ; renderer: %s version str: %s ; GLSL version str: %s", cvendor, renderer ? renderer : "N/A", versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A");
if (renderer) {
strncpy(gl_extensions.model, renderer, sizeof(gl_extensions.model));
gl_extensions.model[sizeof(gl_extensions.model) - 1] = 0;
}
if (!gl_extensions.IsGLES) {
// For desktop GL, grab the version and attempt to parse.
char buffer[64] = { 0 };
if (versionStr) {
strncpy(buffer, versionStr, 63);
}
const char *lastNumStart = buffer;
int numVer = 0;
int len = (int)strlen(buffer);
for (int i = 0; i < len && numVer < 3; i++) {
if (buffer[i] == '.') {
buffer[i] = 0;
gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
i++;
lastNumStart = buffer + i;
}
}
if (numVer < 3)
gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
// If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable
// all the same modern paths.
// Most of it could be enabled on lower GPUs as well, but let's start this way.
if (gl_extensions.VersionGEThan(4, 3, 0)) {
gl_extensions.GLES3 = true;
}
} else {
// Start by assuming we're at 2.0.
gl_extensions.ver[0] = 2;
#ifdef USING_GLES2
#ifdef GL_MAJOR_VERSION
// Before grabbing the values, reset the error.
glGetError();
glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]);
glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]);
// We check error here to detect if these properties were supported.
if (glGetError() != GL_NO_ERROR) {
// They weren't, reset to GLES 2.0.
gl_extensions.ver[0] = 2;
gl_extensions.ver[1] = 0;
}
#endif
// If the above didn't give us a version, or gave us a crazy version, fallback.
if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) {
// Try to load GLES 3.0 only if "3.0" found in version
// This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited
// number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584.
bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0");
bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1
if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) {
gl_extensions.ver[0] = 3;
if (gl_3_1_in_string) {
gl_extensions.ver[1] = 1;
}
gl_extensions.GLES3 = true;
// Though, let's ban Mali from the GLES 3 path for now, see #4078
if (strstr(renderer, "Mali") != 0) {
gl_extensions.GLES3 = false;
}
} else {
// Just to be safe.
gl_extensions.ver[0] = 2;
gl_extensions.ver[1] = 0;
}
} else {
// Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here.
if (gl_extensions.ver[0] >= 3) {
gl_extensions.GLES3 = gl3stubInit();
}
}
#endif
if (gl_extensions.GLES3) {
if (gl_extensions.ver[1] >= 1) {
ILOG("OpenGL ES 3.1 support detected!\n");
} else {
ILOG("OpenGL ES 3.0 support detected!\n");
}
}
}
const char *extString = (const char *)glGetString(GL_EXTENSIONS);
if (extString) {
g_all_gl_extensions = extString;
} else {
g_all_gl_extensions = "";
extString = "";
}
#ifdef WIN32
const char *wglString = 0;
if (wglGetExtensionsStringEXT)
wglString = wglGetExtensionsStringEXT();
if (wglString) {
gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0;
g_all_egl_extensions = wglString;
} else {
g_all_egl_extensions = "";
}
#elif !defined(USING_GLES2)
// const char *glXString = glXQueryExtensionString();
// gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0;
#endif
// Check the desktop extension instead of the OES one. They are very similar.
// Also explicitly check those ATI devices that claims to support npot
gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0
&& !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0)));
gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0;
gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0;
gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0;
gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0);
gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0;
gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0;
gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0;
if (gl_extensions.IsGLES) {
gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0;
gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3;
gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0;
gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0;
gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0;
gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0;
gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0;
gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0;
gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0;
gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0;
gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0;
#if defined(ANDROID) || defined(BLACKBERRY)
// On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though.
// https://twitter.com/ID_AA_Carmack/status/387383037794603008
#ifdef _DEBUG
void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1");
void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2");
DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2);
#endif
if (gl_extensions.NV_copy_image) {
glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV");
}
if (gl_extensions.NV_framebuffer_blit) {
glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV");
}
gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0;
if (gl_extensions.OES_vertex_array_object) {
glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress ( "glGenVertexArraysOES" );
glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress ( "glBindVertexArrayOES" );
glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress ( "glDeleteVertexArraysOES" );
glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress ( "glIsVertexArrayOES" );
}
// Hm, this should be available on iOS too.
gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0;
if (gl_extensions.EXT_discard_framebuffer) {
glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");
}
#else
gl_extensions.OES_vertex_array_object = false;
gl_extensions.EXT_discard_framebuffer = false;
#endif
} else {
// Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc)
gl_extensions.EXT_blend_minmax = true;
gl_extensions.EXT_unpack_subimage = true;
}
// GLES 3 subsumes many ES2 extensions.
if (gl_extensions.GLES3) {
gl_extensions.EXT_unpack_subimage = true;
}
#if defined(ANDROID) || defined(BLACKBERRY)
if (gl_extensions.OES_mapbuffer) {
glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress( "glMapBufferOES" );
}
// Look for EGL extensions
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
const char *eglString = eglQueryString(display, EGL_EXTENSIONS);
if (eglString) {
g_all_egl_extensions = eglString;
gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0;
gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0;
if (gl_extensions.EGL_NV_system_time) {
eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC) eglGetProcAddress("eglGetSystemTimeNV");
eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) eglGetProcAddress("eglGetSystemTimeFrequencyNV");
}
} else {
g_all_egl_extensions = "";
}
#endif
// This is probably a waste of time, implementations lie.
if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) {
const GLint precisions[6] = {
GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT,
GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT
};
GLint shaderTypes[2] = {
GL_VERTEX_SHADER, GL_FRAGMENT_SHADER
};
for (int st = 0; st < 2; st++) {
for (int p = 0; p < 6; p++) {
glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[st][p]);
}
}
}
gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0;
gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0;
gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0;
gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0;
ProcessGPUFeatures();
int error = glGetError();
if (error)
ELOG("GL error in init: %i", error);
}
void OpenGLState::SetVSyncInterval(int interval) {
#ifdef _WIN32
if (wglSwapIntervalEXT)
wglSwapIntervalEXT(interval);
#endif
}

View File

@ -1,322 +0,0 @@
#pragma once
#include <functional>
#include <string.h>
#include <string>
#include "gfx/gl_common.h"
#include "gfx_es2/gpu_features.h"
#ifdef USING_GLES2
#ifndef GL_MIN_EXT
#define GL_MIN_EXT 0x8007
#endif
#ifndef GL_MAX_EXT
#define GL_MAX_EXT 0x8008
#endif
#if defined(ANDROID) || defined(BLACKBERRY)
#include <EGL/egl.h>
// Additional extensions not included in GLES2/gl2ext.h from the NDK
typedef uint64_t EGLuint64NV;
typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void);
typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void);
extern PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
extern PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
typedef GLvoid* (GL_APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
extern PFNGLMAPBUFFERPROC glMapBuffer;
typedef void (EGLAPIENTRYP PFNGLDRAWTEXTURENVPROC) (GLuint texture, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1);
extern PFNGLDRAWTEXTURENVPROC glDrawTextureNV;
typedef void (EGLAPIENTRYP PFNGLCOPYIMAGESUBDATANVPROC) (GLuint srcName, GLenum
srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName,
GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei
width, GLsizei height, GLsizei depth);
extern PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV;
#ifndef ARM64
typedef void (EGLAPIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (
GLint srcX0, GLint srcY0, GLint srcX1, GLuint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLuint dstY1,
GLint mask, GLenum filter);
#endif
extern PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV;
extern PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
extern PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
extern PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
extern PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
#endif
// Rename standard functions to the OES version.
#define glGenVertexArrays glGenVertexArraysOES
#define glBindVertexArray glBindVertexArrayOES
#define glDeleteVertexArrays glDeleteVertexArraysOES
#define glIsVertexArray glIsVertexArrayOES
#if !defined(BLACKBERRY)
#ifndef GL_READ_FRAMEBUFFER
#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER
#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER
#endif
#ifndef GL_DEPTH_COMPONENT24
#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES
#endif
#endif
#ifndef GL_RGBA8
#define GL_RGBA8 GL_RGBA
#endif
#endif /* EGL_NV_system_time */
#ifndef GL_DEPTH24_STENCIL8_OES
#define GL_DEPTH24_STENCIL8_OES 0x88F0
#endif
// 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<GLenum cap, bool init>
class BoolState {
private:
bool _value;
public:
BoolState() : _value(init) {
OpenGLState::state_count++;
}
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) { \
OpenGLState::state_count++; \
} \
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) { \
OpenGLState::state_count++; \
} \
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 STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \
class SavedState3_##func { \
p1type p1; \
p2type p2; \
p3type p3; \
public: \
SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \
OpenGLState::state_count++; \
} \
inline void set(p1type newp1, p2type newp2, p3type newp3) { \
if(newp1 != p1 || newp2 != p2 || newp3 != p3) { \
p1 = newp1; \
p2 = newp2; \
p3 = newp3; \
func(p1, p2, p3); \
} \
} \
inline void restore() { \
func(p1, p2, p3); \
} \
}
#define STATE4(func, p1type, p2type, p3type, p4type, p1def, p2def, p3def, p4def) \
class SavedState4_##func { \
p1type p1; \
p2type p2; \
p3type p3; \
p4type p4; \
public: \
SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \
OpenGLState::state_count++; \
} \
inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \
if(newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \
p1 = newp1; \
p2 = newp2; \
p3 = newp3; \
p4 = newp4; \
func(p1, p2, p3, p4); \
} \
} \
inline void restore() { \
func(p1, p2, p3, p4); \
} \
}
#define STATEFLOAT4(func, def) \
class SavedState4_##func { \
float p[4]; \
public: \
SavedState4_##func() { \
for (int i = 0; i < 4; i++) {p[i] = def;} \
OpenGLState::state_count++; \
} \
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]); \
} \
}
#define STATEBIND(func, target) \
class SavedBind_##func_##target { \
GLuint val_; \
public: \
SavedBind_##func_##target() { \
val_ = 0; \
OpenGLState::state_count++; \
} \
inline void bind(GLuint val) { \
if (val_ != val) { \
func(target, val); \
val_ = val; \
} \
} \
inline void unbind() { \
bind(0); \
} \
inline void restore() { \
func(target, val_); \
} \
}
bool initialized;
public:
static int state_count;
OpenGLState() : initialized(false) {}
void Initialize();
void Restore();
// When adding a state here, don't forget to add it to OpenGLState::Restore() too
// Blending
BoolState<GL_BLEND, false> blend;
STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate;
// On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least but I don't think it's true in practice)
STATE2(glBlendEquationSeparate, GLenum, GLenum, GL_FUNC_ADD, GL_FUNC_ADD) blendEquationSeparate;
STATEFLOAT4(glBlendColor, 1.0f) blendColor;
// Logic Ops. Not available on OpenGL ES at all.
#if !defined(USING_GLES2)
BoolState<GL_COLOR_LOGIC_OP, false> colorLogicOp;
STATE1(glLogicOp, GLenum, GL_COPY) logicOp;
#endif
// Dither
BoolState<GL_DITHER, false> dither;
// Cull Face
BoolState<GL_CULL_FACE, false> cullFace;
STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode;
STATE1(glFrontFace, GLenum, GL_CCW) frontFace;
// Depth Test
BoolState<GL_DEPTH_TEST, false> depthTest;
#if defined(USING_GLES2)
STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange;
#else
STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange;
#endif
STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc;
STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite;
// Color Mask
STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask;
// Viewport
STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport;
// Scissor Test
BoolState<GL_SCISSOR_TEST, false> scissorTest;
STATE4(glScissor, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) scissorRect;
// Stencil Test
BoolState<GL_STENCIL_TEST, false> stencilTest;
STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp;
STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc;
STATE1(glStencilMask, GLuint, 0xFF) stencilMask;
STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer;
STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer;
// Only works on Win32, all other platforms are "force-vsync"
void SetVSyncInterval(int interval); // one of the above VSYNC, or a higher number for multi-frame waits (could be useful for 30hz games)
};
#undef STATE1
#undef STATE2
extern OpenGLState glstate;
extern std::string g_all_gl_extensions;
extern std::string g_all_egl_extensions;
void CheckGLExtensions();

View File

@ -1,7 +1,38 @@
#include <cstring>
#include "base/logging.h"
#include "base/stringutil.h"
#include "gfx/gl_common.h"
#include "gfx_es2/gpu_features.h"
#ifdef _WIN32
#include "GL/wglew.h"
#endif
#if defined(USING_GLES2)
#if defined(ANDROID) || defined(BLACKBERRY)
PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC eglGetSystemTimeFrequencyNV;
PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
PFNGLDRAWTEXTURENVPROC glDrawTextureNV;
PFNGLCOPYIMAGESUBDATANVPROC glCopyImageSubDataNV;
PFNGLBLITFRAMEBUFFERNVPROC glBlitFramebufferNV;
PFNGLMAPBUFFERPROC glMapBuffer;
PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT;
PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOES;
PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOES;
PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOES;
PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES;
#endif
#ifndef IOS
#include "EGL/egl.h"
#endif
#endif
GLExtensions gl_extensions;
std::string g_all_gl_extensions;
std::string g_all_egl_extensions;
bool GLExtensions::VersionGEThan(int major, int minor, int sub) {
if (gl_extensions.ver[0] > major)
return true;
@ -37,3 +68,290 @@ void ProcessGPUFeatures() {
gl_extensions.bugs |= BUG_PVR_GENMIPMAP_HEIGHT_GREATER;
}
}
// http://stackoverflow.com/questions/16147700/opengl-es-using-tegra-specific-extensions-gl-ext-texture-array
void CheckGLExtensions() {
// Make sure to only do this once. It's okay to call CheckGLExtensions from wherever.
static bool done = false;
if (done)
return;
done = true;
memset(&gl_extensions, 0, sizeof(gl_extensions));
#ifdef USING_GLES2
gl_extensions.IsGLES = true;
#endif
const char *renderer = (const char *)glGetString(GL_RENDERER);
const char *versionStr = (const char *)glGetString(GL_VERSION);
const char *glslVersionStr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
// Check vendor string to try and guess GPU
const char *cvendor = (char *)glGetString(GL_VENDOR);
// TODO: move this stuff to gpu_features.cpp
if (cvendor) {
const std::string vendor = StripSpaces(std::string(cvendor));
if (vendor == "NVIDIA Corporation"
|| vendor == "Nouveau"
|| vendor == "nouveau") {
gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA;
} else if (vendor == "Advanced Micro Devices, Inc."
|| vendor == "ATI Technologies Inc.") {
gl_extensions.gpuVendor = GPU_VENDOR_AMD;
} else if (vendor == "Intel"
|| vendor == "Intel Inc."
|| vendor == "Intel Corporation"
|| vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel
gl_extensions.gpuVendor = GPU_VENDOR_INTEL;
} else if (vendor == "ARM") {
gl_extensions.gpuVendor = GPU_VENDOR_ARM;
} else if (vendor == "Imagination Technologies") {
gl_extensions.gpuVendor = GPU_VENDOR_POWERVR;
} else if (vendor == "Qualcomm") {
gl_extensions.gpuVendor = GPU_VENDOR_ADRENO;
} else if (vendor == "Broadcom") {
gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM;
// Just for reference: Galaxy Y has renderer == "VideoCore IV HW"
} else {
gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
}
} else {
gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN;
}
ILOG("GPU Vendor : %s ; renderer: %s version str: %s ; GLSL version str: %s", cvendor, renderer ? renderer : "N/A", versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A");
if (renderer) {
strncpy(gl_extensions.model, renderer, sizeof(gl_extensions.model));
gl_extensions.model[sizeof(gl_extensions.model) - 1] = 0;
}
if (!gl_extensions.IsGLES) {
// For desktop GL, grab the version and attempt to parse.
char buffer[64] = { 0 };
if (versionStr) {
strncpy(buffer, versionStr, 63);
}
const char *lastNumStart = buffer;
int numVer = 0;
int len = (int)strlen(buffer);
for (int i = 0; i < len && numVer < 3; i++) {
if (buffer[i] == '.') {
buffer[i] = 0;
gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
i++;
lastNumStart = buffer + i;
}
}
if (numVer < 3)
gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10);
// If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable
// all the same modern paths.
// Most of it could be enabled on lower GPUs as well, but let's start this way.
if (gl_extensions.VersionGEThan(4, 3, 0)) {
gl_extensions.GLES3 = true;
}
} else {
// Start by assuming we're at 2.0.
gl_extensions.ver[0] = 2;
#ifdef USING_GLES2
#ifdef GL_MAJOR_VERSION
// Before grabbing the values, reset the error.
glGetError();
glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]);
glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]);
// We check error here to detect if these properties were supported.
if (glGetError() != GL_NO_ERROR) {
// They weren't, reset to GLES 2.0.
gl_extensions.ver[0] = 2;
gl_extensions.ver[1] = 0;
}
#endif
// If the above didn't give us a version, or gave us a crazy version, fallback.
if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) {
// Try to load GLES 3.0 only if "3.0" found in version
// This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited
// number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584.
bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0");
bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1
if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) {
gl_extensions.ver[0] = 3;
if (gl_3_1_in_string) {
gl_extensions.ver[1] = 1;
}
gl_extensions.GLES3 = true;
// Though, let's ban Mali from the GLES 3 path for now, see #4078
if (strstr(renderer, "Mali") != 0) {
gl_extensions.GLES3 = false;
}
} else {
// Just to be safe.
gl_extensions.ver[0] = 2;
gl_extensions.ver[1] = 0;
}
} else {
// Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here.
if (gl_extensions.ver[0] >= 3) {
gl_extensions.GLES3 = gl3stubInit();
}
}
#endif
if (gl_extensions.GLES3) {
if (gl_extensions.ver[1] >= 1) {
ILOG("OpenGL ES 3.1 support detected!\n");
} else {
ILOG("OpenGL ES 3.0 support detected!\n");
}
}
}
const char *extString = (const char *)glGetString(GL_EXTENSIONS);
if (extString) {
g_all_gl_extensions = extString;
} else {
g_all_gl_extensions = "";
extString = "";
}
#ifdef WIN32
const char *wglString = 0;
if (wglGetExtensionsStringEXT)
wglString = wglGetExtensionsStringEXT();
if (wglString) {
gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0;
g_all_egl_extensions = wglString;
} else {
g_all_egl_extensions = "";
}
#elif !defined(USING_GLES2)
// const char *glXString = glXQueryExtensionString();
// gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0;
#endif
// Check the desktop extension instead of the OES one. They are very similar.
// Also explicitly check those ATI devices that claims to support npot
gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0
&& !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0)));
gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0;
gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0;
gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0;
gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0);
gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0;
gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0;
gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0;
if (gl_extensions.IsGLES) {
gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0;
gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3;
gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0;
gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0;
gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0;
gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0;
gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0;
gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0;
gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0;
gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0;
gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0;
#if defined(ANDROID) || defined(BLACKBERRY)
// On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though.
// https://twitter.com/ID_AA_Carmack/status/387383037794603008
#ifdef _DEBUG
void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1");
void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2");
DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2);
#endif
if (gl_extensions.NV_copy_image) {
glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV");
}
if (gl_extensions.NV_framebuffer_blit) {
glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV");
}
gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0;
if (gl_extensions.OES_vertex_array_object) {
glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES");
glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES");
glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES");
glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES");
}
// Hm, this should be available on iOS too.
gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0;
if (gl_extensions.EXT_discard_framebuffer) {
glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT");
}
#else
gl_extensions.OES_vertex_array_object = false;
gl_extensions.EXT_discard_framebuffer = false;
#endif
} else {
// Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc)
gl_extensions.EXT_blend_minmax = true;
gl_extensions.EXT_unpack_subimage = true;
}
// GLES 3 subsumes many ES2 extensions.
if (gl_extensions.GLES3) {
gl_extensions.EXT_unpack_subimage = true;
}
#if defined(ANDROID) || defined(BLACKBERRY)
if (gl_extensions.OES_mapbuffer) {
glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress("glMapBufferOES");
}
// Look for EGL extensions
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
const char *eglString = eglQueryString(display, EGL_EXTENSIONS);
if (eglString) {
g_all_egl_extensions = eglString;
gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0;
gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0;
if (gl_extensions.EGL_NV_system_time) {
eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC)eglGetProcAddress("eglGetSystemTimeNV");
eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)eglGetProcAddress("eglGetSystemTimeFrequencyNV");
}
} else {
g_all_egl_extensions = "";
}
#endif
// This is probably a waste of time, implementations lie.
if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) {
const GLint precisions[6] = {
GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT,
GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT
};
GLint shaderTypes[2] = {
GL_VERTEX_SHADER, GL_FRAGMENT_SHADER
};
for (int st = 0; st < 2; st++) {
for (int p = 0; p < 6; p++) {
glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[st][p]);
}
}
}
gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0;
gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0;
gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0;
gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0;
ProcessGPUFeatures();
int error = glGetError();
if (error)
ELOG("GL error in init: %i", error);
}

View File

@ -90,8 +90,11 @@ struct GLExtensions {
extern GLExtensions gl_extensions;
// Call this after filling out vendor etc to lookup the bugs etc.
// Only needs to be called once. Currently called by CheckGLExtensions().
void ProcessGPUFeatures();
extern std::string g_all_gl_extensions;
extern std::string g_all_egl_extensions;
void CheckGLExtensions();

View File

@ -248,10 +248,8 @@
<ClInclude Include="gfx\texture_atlas.h" />
<ClInclude Include="gfx_es2\draw_buffer.h" />
<ClInclude Include="gfx_es2\draw_text.h" />
<ClInclude Include="gfx_es2\fbo.h" />
<ClInclude Include="gfx_es2\gl3stub.h" />
<ClInclude Include="gfx_es2\glsl_program.h" />
<ClInclude Include="gfx_es2\gl_state.h" />
<ClInclude Include="gfx_es2\gpu_features.h" />
<ClInclude Include="gfx_es2\vertex_format.h" />
<ClInclude Include="i18n\i18n.h" />
@ -734,7 +732,6 @@
<ClCompile Include="gfx\texture_gen.cpp" />
<ClCompile Include="gfx_es2\draw_buffer.cpp" />
<ClCompile Include="gfx_es2\draw_text.cpp" />
<ClCompile Include="gfx_es2\fbo.cpp" />
<ClCompile Include="gfx_es2\gl3stub.c">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
@ -742,7 +739,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="gfx_es2\glsl_program.cpp" />
<ClCompile Include="gfx_es2\gl_state.cpp" />
<ClCompile Include="gfx_es2\gpu_features.cpp" />
<ClCompile Include="gfx_es2\vertex_format.cpp" />
<ClCompile Include="i18n\i18n.cpp" />
@ -799,4 +795,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -54,9 +54,6 @@
<ClInclude Include="gfx_es2\draw_buffer.h">
<Filter>gfx</Filter>
</ClInclude>
<ClInclude Include="gfx_es2\fbo.h">
<Filter>gfx</Filter>
</ClInclude>
<ClInclude Include="gfx_es2\glsl_program.h">
<Filter>gfx</Filter>
</ClInclude>
@ -219,9 +216,6 @@
<ClInclude Include="ext\stb_vorbis\stb_vorbis.h">
<Filter>ext</Filter>
</ClInclude>
<ClInclude Include="gfx_es2\gl_state.h">
<Filter>gfx</Filter>
</ClInclude>
<ClInclude Include="gfx_es2\gpu_features.h">
<Filter>gfx</Filter>
</ClInclude>
@ -387,9 +381,6 @@
<ClCompile Include="gfx_es2\draw_buffer.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="gfx_es2\fbo.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="gfx_es2\glsl_program.cpp">
<Filter>gfx</Filter>
</ClCompile>
@ -524,9 +515,6 @@
<ClCompile Include="base\BlackberryMain.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="gfx_es2\gl_state.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="gfx_es2\gpu_features.cpp">
<Filter>gfx</Filter>
</ClCompile>
@ -925,4 +913,4 @@
<UniqueIdentifier>{06c6305a-a646-485b-85b9-645a24dd6553}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View File

@ -7,7 +7,8 @@
#include "image/zim_load.h"
#include "math/lin/matrix4x4.h"
#include "thin3d/thin3d.h"
#include "gfx_es2/gl_state.h"
#include "gfx/gl_common.h"
#include "gfx_es2/gpu_features.h"
#include "gfx/gl_lost_manager.h"
static const unsigned short compToGL[] = {
@ -91,20 +92,25 @@ public:
// uint32_t fixedColor;
void Apply() {
glstate.blend.set(enabled);
glstate.blendEquationSeparate.set(eqCol, eqAlpha);
glstate.blendFuncSeparate.set(srcCol, dstCol, srcAlpha, dstAlpha);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// glstate.blendColor.set(fixedColor);
if (enabled) {
glEnable(GL_BLEND);
glBlendEquationSeparate(eqCol, eqAlpha);
glBlendFuncSeparate(srcCol, dstCol, srcAlpha, dstAlpha);
} else {
glDisable(GL_BLEND);
}
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// glColorMask(maskBits & 1, (maskBits >> 1) & 1, (maskBits >> 2) & 1, (maskBits >> 3) & 1);
// glBlendColor(fixedColor);
#if !defined(USING_GLES2)
glstate.colorLogicOp.set(logicEnabled);
if (logicEnabled) {
glstate.logicOp.set(logicOp);
glEnable(GL_LOGIC_OP);
glLogicOp(logicOp);
} else {
glDisable(GL_LOGIC_OP);
}
#endif
// glstate.colorMask.set(maskBits & 1, (maskBits >> 1) & 1, (maskBits >> 2) & 1, (maskBits >> 3) & 1);
}
};
@ -116,10 +122,14 @@ public:
// bool stencilTestEnabled; TODO
void Apply() {
glstate.depthTest.set(depthTestEnabled);
glstate.depthFunc.set(depthComp);
glstate.depthWrite.set(depthWriteEnabled);
glstate.stencilTest.disable();
if (depthTestEnabled) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(depthComp);
glDepthMask(depthWriteEnabled);
} else {
glDisable(GL_DEPTH_TEST);
}
glDisable(GL_STENCIL_TEST);
}
};
@ -157,11 +167,7 @@ public:
glBufferSubData(target_, offset, size, data);
}
void Bind() {
if (target_ == GL_ARRAY_BUFFER) {
glstate.arrayBuffer.bind(buffer_);
} else {
glstate.elementArrayBuffer.bind(buffer_);
}
glBindBuffer(target_, buffer_);
}
void GLLost() override {
@ -315,17 +321,25 @@ public:
Thin3DShader *CreateFragmentShader(const char *glsl_source, const char *hlsl_source);
void SetScissorEnabled(bool enable) override {
glstate.scissorTest.set(enable);
if (enable) {
glEnable(GL_SCISSOR_TEST);
} else {
glDisable(GL_SCISSOR_TEST);
}
}
void SetScissorRect(int left, int top, int width, int height) override {
glstate.scissorRect.set(left, targetHeight_ - (top + height), width, height);
glScissor(left, targetHeight_ - (top + height), width, height);
}
void SetViewports(int count, T3DViewport *viewports) override {
// TODO: Add support for multiple viewports.
glstate.viewport.set(viewports[0].TopLeftX, viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height);
glstate.depthRange.set(viewports[0].MinDepth, viewports[0].MaxDepth);
glViewport(viewports[0].TopLeftX, viewports[0].TopLeftY, viewports[0].Width, viewports[0].Height);
#if defined(USING_GLES2)
glDepthRangef(viewports[0].MinDepth, viewports[0].MaxDepth);
#else
glDepthRange(viewports[0].MinDepth, viewports[0].MaxDepth);
#endif
}
void SetTextures(int start, int count, Thin3DTexture **textures) override;
@ -709,9 +723,9 @@ void Thin3DGLContext::SetRenderState(T3DRenderState rs, uint32_t value) {
switch (rs) {
case T3DRenderState::CULL_MODE:
switch (value) {
case T3DCullMode::NO_CULL: glstate.cullFace.disable(); break;
case T3DCullMode::CCW: glstate.cullFace.enable(); glstate.cullFaceMode.set(GL_CCW); break;
case T3DCullMode::CW: glstate.cullFace.enable(); glstate.cullFaceMode.set(GL_CW); break;
case T3DCullMode::NO_CULL: glDisable(GL_CULL_FACE); break;
case T3DCullMode::CCW: glEnable(GL_CULL_FACE); glCullFace(GL_CCW); break; // TODO: Should be GL_FRONT
case T3DCullMode::CW: glEnable(GL_CULL_FACE); glCullFace(GL_CW); break;
}
break;
}
@ -771,7 +785,7 @@ void Thin3DGLContext::Clear(int mask, uint32_t colorval, float depthVal, int ste
glMask |= GL_COLOR_BUFFER_BIT;
}
if (mask & T3DClear::DEPTH) {
#ifdef USING_GLES2
#if defined(USING_GLES2)
glClearDepthf(depthVal);
#else
glClearDepth(depthVal);

View File

@ -2,10 +2,8 @@
#include "ui/ui.h"
#include "ui/view.h"
#include "ui/ui_context.h"
#include "gfx/texture.h"
#include "gfx_es2/draw_buffer.h"
#include "gfx_es2/draw_text.h"
#include "gfx_es2/gl_state.h"
UIContext::UIContext()
: uishader_(0), uitexture_(0), uidrawbuffer_(0), uidrawbufferTop_(0) {