/* * Copyright 2011-2014 Branimir Karadzic. All rights reserved. * License: http://www.opensource.org/licenses/BSD-2-Clause */ #ifndef BGFX_RENDERER_GL_H_HEADER_GUARD #define BGFX_RENDERER_GL_H_HEADER_GUARD #define BGFX_USE_EGL ( (BGFX_CONFIG_RENDERER_OPENGLES2 || BGFX_CONFIG_RENDERER_OPENGLES3) && (BX_PLATFORM_ANDROID || BX_PLATFORM_EMSCRIPTEN || BX_PLATFORM_QNX || BX_PLATFORM_WINDOWS) ) #define BGFX_USE_WGL (BGFX_CONFIG_RENDERER_OPENGL && BX_PLATFORM_WINDOWS) #define BGFX_USE_GL_DYNAMIC_LIB (BX_PLATFORM_LINUX || BX_PLATFORM_OSX || BX_PLATFORM_WINDOWS) #if BGFX_CONFIG_RENDERER_OPENGL # if BGFX_CONFIG_RENDERER_OPENGL >= 31 # include # if BX_PLATFORM_OSX # define GL_ARB_shader_objects // OSX collsion with GLhandleARB in gltypes.h # endif // BX_PLATFORM_OSX # else # if BX_PLATFORM_LINUX # define GL_PROTOTYPES # define GL_GLEXT_LEGACY # include # undef GL_PROTOTYPES # elif BX_PLATFORM_OSX # define GL_GLEXT_LEGACY # define long ptrdiff_t # include # undef long # undef GL_VERSION_1_2 # undef GL_VERSION_1_3 # undef GL_VERSION_1_4 # undef GL_VERSION_1_5 # undef GL_VERSION_2_0 # else # include # endif // BX_PLATFORM_ # include # endif // BGFX_CONFIG_RENDERER_OPENGL >= 31 #elif BGFX_CONFIG_RENDERER_OPENGLES2 || BGFX_CONFIG_RENDERER_OPENGLES3 typedef double GLdouble; # if BGFX_CONFIG_RENDERER_OPENGLES2 # if BX_PLATFORM_IOS # include # include //#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 #define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 #define GL_TEXTURE_3D_OES 0x806F #define GL_SAMPLER_3D_OES 0x8B5F #define GL_TEXTURE_WRAP_R_OES 0x8072 #define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 # else # include # include # include # endif // BX_PLATFORM_ typedef int64_t GLint64; typedef uint64_t GLuint64; # define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES # define GL_HALF_FLOAT GL_HALF_FLOAT_OES # define GL_RGBA8 GL_RGBA8_OES # define GL_RGB10_A2 GL_RGB10_A2_EXT # define GL_R16F GL_R16F_EXT # define GL_R32F GL_R32F_EXT # define GL_UNSIGNED_INT_2_10_10_10_REV GL_UNSIGNED_INT_2_10_10_10_REV_EXT # define GL_TEXTURE_3D GL_TEXTURE_3D_OES # define GL_SAMPLER_3D GL_SAMPLER_3D_OES # define GL_TEXTURE_WRAP_R GL_TEXTURE_WRAP_R_OES # define GL_MIN GL_MIN_EXT # define GL_MAX GL_MAX_EXT # define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES # define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_OES # define GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT32_OES # define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES # elif BGFX_CONFIG_RENDERER_OPENGLES3 # include # include # include # endif // BGFX_CONFIG_RENDERER_ # if BGFX_USE_EGL # include "glcontext_egl.h" # endif // BGFX_USE_EGL # if BX_PLATFORM_EMSCRIPTEN # include # endif // BX_PLATFORM_EMSCRIPTEN #endif // BGFX_CONFIG_RENDERER_OPENGL #ifndef GL_LUMINANCE # define GL_LUMINANCE 0x1909 #endif // GL_LUMINANCE #ifndef GL_BGRA_EXT # define GL_BGRA_EXT 0x80E1 #endif // GL_BGRA_EXT #ifndef GL_R16F_EXT # define GL_R16F_EXT 0x822D #endif // GL_R16F_EXT #ifndef GL_R32F_EXT # define GL_R32F_EXT 0x822E #endif // GL_R32F_EXT #ifndef GL_RGB10_A2_EXT # define GL_RGB10_A2_EXT 0x8059 #endif // GL_RGB10_A2_EXT #ifndef GL_RGBA16 # define GL_RGBA16 0x805B #endif // GL_RGBA16 #ifndef GL_RGBA16F # define GL_RGBA16F 0x881A #endif // GL_RGBA16F #ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT # define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #endif // GL_COMPRESSED_RGB_S3TC_DXT1_EXT #ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT # define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #endif // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT #ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT # define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #endif // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT #ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT # define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 #endif // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT #ifndef GL_COMPRESSED_LUMINANCE_LATC1_EXT # define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 #endif // GL_COMPRESSED_LUMINANCE_LATC1_EXT #ifndef GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT # define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 #endif // GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT #ifndef GL_COMPRESSED_RED_RGTC1_EXT # define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB #endif // GL_COMPRESSED_RED_RGTC1_EXT #ifndef GL_COMPRESSED_RED_GREEN_RGTC2_EXT # define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD #endif // GL_COMPRESSED_RED_GREEN_RGTC2_EXT #ifndef GL_ETC1_RGB8_OES # define GL_ETC1_RGB8_OES 0x8D64 #endif // GL_ETC1_RGB8_OES #ifndef GL_COMPRESSED_RGB8_ETC2 # define GL_COMPRESSED_RGB8_ETC2 0x9274 #endif // GL_COMPRESSED_RGB8_ETC2 #ifndef GL_COMPRESSED_RGBA8_ETC2_EAC # define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 #endif // GL_COMPRESSED_RGBA8_ETC2_EAC #ifndef GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 # define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 #endif // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 #ifndef GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG # define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 #endif // GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG #ifndef GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG # define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 #endif // GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG #ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG # define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 #endif // GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG #ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG # define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 #endif // GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG #ifndef GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG # define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 #endif // GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG #ifndef GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG # define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 #endif // GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG #ifndef GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE # define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 #endif // GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT # define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #endif // GL_TEXTURE_MAX_ANISOTROPY_EXT #ifndef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT # define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF #endif // GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT #ifndef GL_MAX_SAMPLES # define GL_MAX_SAMPLES 0x8D57 #endif // GL_MAX_SAMPLES #ifndef GL_MAX_COLOR_ATTACHMENTS # define GL_MAX_COLOR_ATTACHMENTS 0x8CDF #endif // GL_MAX_COLOR_ATTACHMENTS #ifndef GL_QUERY_RESULT # define GL_QUERY_RESULT 0x8866 #endif // GL_QUERY_RESULT #ifndef GL_READ_FRAMEBUFFER # define GL_READ_FRAMEBUFFER 0x8CA8 #endif /// GL_READ_FRAMEBUFFER #ifndef GL_DRAW_FRAMEBUFFER # define GL_DRAW_FRAMEBUFFER 0x8CA9 #endif // GL_DRAW_FRAMEBUFFER #ifndef GL_TIME_ELAPSED # define GL_TIME_ELAPSED 0x88BF #endif // GL_TIME_ELAPSED #ifndef GL_VBO_FREE_MEMORY_ATI # define GL_VBO_FREE_MEMORY_ATI 0x87FB #endif // GL_VBO_FREE_MEMORY_ATI #ifndef GL_TEXTURE_FREE_MEMORY_ATI # define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC #endif // GL_TEXTURE_FREE_MEMORY_ATI #ifndef GL_RENDERBUFFER_FREE_MEMORY_ATI # define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD #endif // GL_RENDERBUFFER_FREE_MEMORY_ATI // http://developer.download.nvidia.com/opengl/specs/GL_NVX_gpu_memory_info.txt #ifndef GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX # define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 #endif // GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX #ifndef GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX # define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 #endif // GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX #ifndef GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX # define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 #endif // GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX #ifndef GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX # define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A #endif // GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX #ifndef GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX # define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B #endif // GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX #ifndef GL_UNPACK_ROW_LENGTH # define GL_UNPACK_ROW_LENGTH 0x0CF2 #endif // GL_UNPACK_ROW_LENGTH #ifndef GL_DEPTH_STENCIL # define GL_DEPTH_STENCIL 0x84F9 #endif // GL_DEPTH_STENCIL #ifndef GL_DEPTH_COMPONENT32 # define GL_DEPTH_COMPONENT32 0x81A7 #endif // GL_DEPTH_COMPONENT32 #ifndef GL_DEPTH_COMPONENT32F # define GL_DEPTH_COMPONENT32F 0x8CAC #endif // GL_DEPTH_COMPONENT32F #ifndef GL_DEPTH_STENCIL_ATTACHMENT # define GL_DEPTH_STENCIL_ATTACHMENT 0x821A #endif // GL_DEPTH_STENCIL_ATTACHMENT #ifndef GL_TEXTURE_COMPARE_MODE # define GL_TEXTURE_COMPARE_MODE 0x884C #endif // GL_TEXTURE_COMPARE_MODE #ifndef GL_TEXTURE_COMPARE_FUNC # define GL_TEXTURE_COMPARE_FUNC 0x884D #endif // GL_TEXTURE_COMPARE_FUNC #ifndef GL_COMPARE_REF_TO_TEXTURE # define GL_COMPARE_REF_TO_TEXTURE 0x884E #endif // GL_COMPARE_REF_TO_TEXTURE #ifndef GL_SAMPLER_2D_SHADOW # define GL_SAMPLER_2D_SHADOW 0x8B62 #endif // GL_SAMPLER_2D_SHADOW #if BX_PLATFORM_NACL # include "glcontext_ppapi.h" #elif BX_PLATFORM_WINDOWS # include #elif BX_PLATFORM_LINUX # include "glcontext_glx.h" #elif BX_PLATFORM_OSX # include "glcontext_nsgl.h" #elif BX_PLATFORM_IOS # include "glcontext_eagl.h" #endif // BX_PLATFORM_ #if BGFX_USE_WGL # include "glcontext_wgl.h" #endif // BGFX_USE_WGL #ifndef GL_APIENTRY # define GL_APIENTRY APIENTRY #endif // GL_APIENTRY #ifndef GL_APIENTRYP # define GL_APIENTRYP GL_APIENTRY* #endif // GL_APIENTRYP #if !BGFX_CONFIG_RENDERER_OPENGL # define glClearDepth glClearDepthf #endif // !BGFX_CONFIG_RENDERER_OPENGL namespace bgfx { # define _GL_CHECK(_call) \ do { \ /*BX_TRACE(#_call);*/ \ _call; \ GLenum err = glGetError(); \ BX_CHECK(0 == err, #_call "; glError 0x%x %d", err, err); \ } while (0) #if BGFX_CONFIG_DEBUG # define GL_CHECK(_call) _GL_CHECK(_call) #else # define GL_CHECK(_call) _call #endif // BGFX_CONFIG_DEBUG #define GL_IMPORT_TYPEDEFS 1 #define GL_IMPORT(_optional, _proto, _func, _import) extern _proto _func #include "glimports.h" void dumpExtensions(const char* _extensions); class ConstantBuffer; class VaoStateCache { public: GLuint add(uint32_t _hash) { invalidate(_hash); GLuint arrayId; GL_CHECK(glGenVertexArrays(1, &arrayId) ); m_hashMap.insert(stl::make_pair(_hash, arrayId) ); return arrayId; } GLuint find(uint32_t _hash) { HashMap::iterator it = m_hashMap.find(_hash); if (it != m_hashMap.end() ) { return it->second; } return UINT32_MAX; } void invalidate(uint32_t _hash) { GL_CHECK(glBindVertexArray(0) ); HashMap::iterator it = m_hashMap.find(_hash); if (it != m_hashMap.end() ) { GL_CHECK(glDeleteVertexArrays(1, &it->second) ); m_hashMap.erase(it); } } void invalidate() { GL_CHECK(glBindVertexArray(0) ); for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it) { GL_CHECK(glDeleteVertexArrays(1, &it->second) ); } m_hashMap.clear(); } private: typedef stl::unordered_map HashMap; HashMap m_hashMap; }; class VaoCacheRef { public: void add(uint32_t _hash) { m_vaoSet.insert(_hash); } void invalidate(VaoStateCache& _vaoCache) { for (VaoSet::iterator it = m_vaoSet.begin(), itEnd = m_vaoSet.end(); it != itEnd; ++it) { _vaoCache.invalidate(*it); } m_vaoSet.clear(); } typedef stl::unordered_set VaoSet; VaoSet m_vaoSet; }; class SamplerStateCache { public: GLuint add(uint32_t _hash) { invalidate(_hash); GLuint samplerId; GL_CHECK(glGenSamplers(1, &samplerId) ); m_hashMap.insert(stl::make_pair(_hash, samplerId) ); return samplerId; } GLuint find(uint32_t _hash) { HashMap::iterator it = m_hashMap.find(_hash); if (it != m_hashMap.end() ) { return it->second; } return UINT32_MAX; } void invalidate(uint32_t _hash) { HashMap::iterator it = m_hashMap.find(_hash); if (it != m_hashMap.end() ) { GL_CHECK(glDeleteSamplers(1, &it->second) ); m_hashMap.erase(it); } } void invalidate() { for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it) { GL_CHECK(glDeleteSamplers(1, &it->second) ); } m_hashMap.clear(); } private: typedef stl::unordered_map HashMap; HashMap m_hashMap; }; struct IndexBuffer { void create(uint32_t _size, void* _data) { m_size = _size; GL_CHECK(glGenBuffers(1, &m_id) ); BX_CHECK(0 != m_id, "Failed to generate buffer id."); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_id) ); GL_CHECK(glBufferData(GL_ELEMENT_ARRAY_BUFFER , _size , _data , (NULL==_data)?GL_DYNAMIC_DRAW:GL_STATIC_DRAW ) ); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); } void update(uint32_t _offset, uint32_t _size, void* _data) { BX_CHECK(0 != m_id, "Updating invalid index buffer."); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_id) ); GL_CHECK(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER , _offset , _size , _data ) ); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); } void destroy(); void add(uint32_t _hash) { m_vcref.add(_hash); } GLuint m_id; uint32_t m_size; VaoCacheRef m_vcref; }; struct VertexBuffer { void create(uint32_t _size, void* _data, VertexDeclHandle _declHandle) { m_size = _size; m_decl = _declHandle; GL_CHECK(glGenBuffers(1, &m_id) ); BX_CHECK(0 != m_id, "Failed to generate buffer id."); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id) ); GL_CHECK(glBufferData(GL_ARRAY_BUFFER , _size , _data , (NULL==_data)?GL_DYNAMIC_DRAW:GL_STATIC_DRAW ) ); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); } void update(uint32_t _offset, uint32_t _size, void* _data) { BX_CHECK(0 != m_id, "Updating invalid vertex buffer."); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id) ); GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER , _offset , _size , _data ) ); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); } void destroy(); void add(uint32_t _hash) { m_vcref.add(_hash); } GLuint m_id; uint32_t m_size; VertexDeclHandle m_decl; VaoCacheRef m_vcref; }; struct Texture { Texture() : m_id(0) , m_rbo(0) , m_target(GL_TEXTURE_2D) , m_fmt(GL_ZERO) , m_type(GL_ZERO) , m_flags(0) , m_currentFlags(UINT32_MAX) , m_numMips(0) { } bool init(GLenum _target, uint32_t _width, uint32_t _height, uint8_t _format, uint8_t _numMips, uint32_t _flags); void create(const Memory* _mem, uint32_t _flags, uint8_t _skip); void destroy(); void update(uint8_t _side, uint8_t _mip, const Rect& _rect, uint16_t _z, uint16_t _depth, uint16_t _pitch, const Memory* _mem); void setSamplerState(uint32_t _flags); void commit(uint32_t _stage, uint32_t _flags); GLuint m_id; GLuint m_rbo; GLenum m_target; GLenum m_fmt; GLenum m_type; uint32_t m_flags; uint32_t m_currentFlags; uint32_t m_width; uint32_t m_height; uint8_t m_numMips; uint8_t m_requestedFormat; uint8_t m_textureFormat; }; struct Shader { Shader() : m_id(0) , m_type(0) , m_hash(0) { } void create(GLenum _type, Memory* _mem); void destroy(); GLuint m_id; GLenum m_type; uint32_t m_hash; }; struct FrameBuffer { FrameBuffer() : m_num(0) { memset(m_fbo, 0, sizeof(m_fbo) ); } void create(uint8_t _num, const TextureHandle* _handles); void destroy(); void resolve(); uint8_t m_num; GLuint m_fbo[2]; uint32_t m_width; uint32_t m_height; }; struct Program { Program() : m_id(0) , m_constantBuffer(NULL) , m_numPredefined(0) { } void create(const Shader& _vsh, const Shader& _fsh); void destroy(); void init(); void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const; void bindInstanceData(uint32_t _stride, uint32_t _baseVertex = 0) const; void commit() { m_constantBuffer->commit(); } void add(uint32_t _hash) { m_vcref.add(_hash); } GLuint m_id; uint8_t m_used[Attrib::Count+1]; // dense GLint m_attributes[Attrib::Count]; // sparse GLint m_instanceData[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT]; GLint m_sampler[BGFX_CONFIG_MAX_TEXTURES]; uint8_t m_numSamplers; ConstantBuffer* m_constantBuffer; PredefinedUniform m_predefined[PredefinedUniform::Count]; uint8_t m_numPredefined; VaoCacheRef m_vcref; }; struct Queries { void create() { glGenQueries(BX_COUNTOF(m_queries), m_queries); } void destroy() { glDeleteQueries(BX_COUNTOF(m_queries), m_queries); } void begin(uint16_t _id, GLenum _target) const { glBeginQuery(_target, m_queries[_id]); } void end(GLenum _target) const { glEndQuery(_target); } uint64_t getResult(uint16_t _id) const { uint64_t result; glGetQueryObjectui64v(m_queries[_id], GL_QUERY_RESULT, &result); return result; } GLuint m_queries[64]; }; } // namespace bgfx #endif // BGFX_RENDERER_GL_H_HEADER_GUARD