/* * Copyright 2011-2012 Branimir Karadzic. All rights reserved. * License: http://www.opensource.org/licenses/BSD-2-Clause */ #ifndef __RENDERER_GL_H__ #define __RENDERER_GL_H__ #if BX_PLATFORM_NACL # include # include # include # include # include #elif BX_PLATFORM_ANDROID # include #elif BX_PLATFORM_WINDOWS # include # include # include #elif BX_PLATFORM_LINUX # include # include # include #endif // BX_PLATFORM_ #ifndef GL_BGRA_EXT # define GL_BGRA_EXT 0x80E1 #endif // GL_BGRA_EXT #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_FRAGMENT_SHADER_DERIVATIVE_HINT_OES # define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B #endif // GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 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) _call // _GL_CHECK(_call) #else # define GL_CHECK(_call) _call #endif // BGFX_CONFIG_DEBUG #if BX_PLATFORM_WINDOWS #define GL_IMPORT(_proto, _func) extern _proto _func #include "glimports.h" #undef GL_IMPORT #endif // BX_PLATFORM_WINDOWS class ConstantBuffer; 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 _size, void* _data) { GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_id) ); GL_CHECK(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER , 0 , _size , _data ) ); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); } void destroy() { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDeleteBuffers(1, &m_id); } GLuint m_id; uint32_t m_size; }; 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 _size, void* _data) { GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id) ); GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER , 0 , _size , _data ) ); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); } void destroy() { GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); GL_CHECK(glDeleteBuffers(1, &m_id) ); } GLuint m_id; uint32_t m_size; VertexDeclHandle m_decl; }; struct Texture { Texture() : m_id(0) , m_target(GL_TEXTURE_2D) { } void create(const Memory* _mem, uint32_t _flags); void createColor(uint32_t _width, uint32_t _height); void createDepth(uint32_t _width, uint32_t _height); void destroy(); GLuint m_id; GLenum m_target; }; struct Shader { void create(GLenum _type, const uint8_t* _code) { m_id = glCreateShader(_type); m_type = _type; if (0 != m_id) { GL_CHECK(glShaderSource(m_id, 1, (const GLchar**)&_code, NULL) ); GL_CHECK(glCompileShader(m_id) ); GLint compiled = 0; GL_CHECK(glGetShaderiv(m_id, GL_COMPILE_STATUS, &compiled) ); if (0 == compiled) { char log[1024]; GL_CHECK(glGetShaderInfoLog(m_id, sizeof(log), NULL, log) ); BX_TRACE("Failed to compile shader. %d: %s", compiled, log); BX_TRACE("\n####\n%s\n####", _code); GL_CHECK(glDeleteShader(m_id) ); } } } void destroy() { GL_CHECK(glDeleteShader(m_id) ); } GLuint m_id; GLenum m_type; }; struct RenderTarget { void create(uint16_t _width, uint16_t _height, uint32_t _flags); void destroy(); GLsizei m_width; GLsizei m_height; Texture m_color; Texture m_depth; GLuint m_fbo; GLuint m_rbo; }; struct Material { void create(const Shader& _vsh, const Shader& _fsh) { m_id = glCreateProgram(); BX_TRACE("material create: %d: %d, %d", m_id, _vsh.m_id, _fsh.m_id); GL_CHECK(glAttachShader(m_id, _vsh.m_id) ); GL_CHECK(glAttachShader(m_id, _fsh.m_id) ); GL_CHECK(glLinkProgram(m_id) ); GLint linked = 0; GL_CHECK(glGetProgramiv(m_id, GL_LINK_STATUS, &linked) ); if (0 == linked) { char log[1024]; GL_CHECK(glGetProgramInfoLog(m_id, sizeof(log), NULL, log) ); BX_TRACE("%d: %s", linked, log); GL_CHECK(glDeleteProgram(m_id) ); return; } init(); } void destroy() { GL_CHECK(glUseProgram(0) ); GL_CHECK(glDeleteProgram(m_id) ); } void init(); void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0); GLuint m_id; uint8_t m_used[Attrib::Count+1]; // dense uint16_t m_attributes[Attrib::Count]; // sparse uint32_t m_enabled; GLuint m_sampler[BGFX_CONFIG_MAX_TEXTURES]; uint8_t m_numSamplers; ConstantBuffer* m_constantBuffer; PredefinedUniform m_predefined[PredefinedUniform::Count]; uint8_t m_numPredefined; }; } // namespace bgfx #endif // __RENDERER_GL_H__