mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-24 19:00:54 +00:00
Merge pull request #288 from hrydgard/move-glstate
Move glstate out to PPSSPP
This commit is contained in:
commit
9ce1822a83
@ -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 \
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
413
gfx_es2/fbo.cpp
413
gfx_es2/fbo.cpp
@ -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 = ¤tReadHandle_;
|
||||
return GL_READ_FRAMEBUFFER;
|
||||
} else {
|
||||
*cached = ¤tDrawHandle_;
|
||||
return GL_DRAW_FRAMEBUFFER;
|
||||
}
|
||||
} else {
|
||||
*cached = ¤tDrawHandle_;
|
||||
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;
|
||||
}
|
@ -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.
|
@ -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
|
||||
}
|
@ -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();
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user