From 98ebe1f07652ab10d58262dcdcd3500c261e3feb Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Sun, 8 Jul 2012 19:10:07 -0700 Subject: [PATCH] Added DX11 renderer stub. --- src/bgfx.cpp | 8 +- src/bgfx_p.h | 12 +- src/config.h | 18 +- src/renderer_d3d11.cpp | 141 ++ src/renderer_d3d9.cpp | 19 +- src/renderer_d3d9.h | 10 +- src/renderer_gl.cpp | 5023 ++++++++++++++++++++-------------------- src/renderer_gl.h | 802 +++---- 8 files changed, 3094 insertions(+), 2939 deletions(-) create mode 100644 src/renderer_d3d11.cpp diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 9a2cf0559..d77788cbe 100644 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -227,7 +227,7 @@ namespace bgfx charsetFillTexture(vga8x16, &rgba[8*pitch], 16, pitch, bpp); m_texture = s_ctx.createTexture(mem, BGFX_TEXTURE_MIN_POINT|BGFX_TEXTURE_MAG_POINT|BGFX_TEXTURE_MIP_POINT, NULL, NULL); -#if BGFX_CONFIG_RENDERER_DIRECT3D +#if BGFX_CONFIG_RENDERER_DIRECT3D9 mem = bgfx::alloc(sizeof(vs_debugfont_hlsl)+1); memcpy(mem->data, vs_debugfont_hlsl, mem->size-1); #else @@ -237,7 +237,7 @@ namespace bgfx mem->data[mem->size-1] = '\0'; bgfx::VertexShaderHandle vsh = bgfx::createVertexShader(mem); -#if BGFX_CONFIG_RENDERER_DIRECT3D +#if BGFX_CONFIG_RENDERER_DIRECT3D9 mem = bgfx::alloc(sizeof(fs_debugfont_hlsl)+1); memcpy(mem->data, fs_debugfont_hlsl, mem->size-1); #else @@ -458,11 +458,11 @@ namespace bgfx RendererType::Enum getRendererType() { -#if BGFX_CONFIG_RENDERER_DIRECT3D +#if BGFX_CONFIG_RENDERER_DIRECT3D9 return RendererType::Direct3D9; #elif BGFX_CONFIG_RENDERER_OPENGL return RendererType::OpenGL; -#elif BGFX_CONFIG_RENDERER_OPENGLES +#elif BGFX_CONFIG_RENDERER_OPENGLES2 return RendererType::OpenGLES; #else return RendererType::Null; diff --git a/src/bgfx_p.h b/src/bgfx_p.h index a1f4aed56..a30393c6c 100644 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -132,6 +132,14 @@ namespace stl = std; #define BGFX_SAMPLER_RENDERTARGET_DEPTH UINT16_C(0x0002) #define BGFX_SAMPLER_TYPE_MASK UINT16_C(0x0003) +#if BGFX_CONFIG_RENDERER_DIRECT3D9 +# define BGFX_RENDERER_NAME "Direct3D 9" +#elif BGFX_CONFIG_RENDERER_OPENGL +# define BGFX_RENDERER_NAME "OpenGL" +#elif BGFX_CONFIG_RENDERER_OPENGLES2 +# define BGFX_RENDERER_NAME "OpenGL ES 2" +#endif // BGFX_CONFIG_RENDERER_ + namespace bgfx { extern const uint32_t g_constantTypeSize[ConstantType::Count]; @@ -1088,7 +1096,7 @@ namespace bgfx void setInstanceDataBuffer(const InstanceDataBuffer* _idb) { -#if BGFX_CONFIG_RENDERER_OPENGLES +#if BGFX_CONFIG_RENDERER_OPENGLES2 #else m_state.m_instanceDataOffset = _idb->offset; m_state.m_instanceDataStride = _idb->stride; @@ -1878,7 +1886,7 @@ namespace bgfx const InstanceDataBuffer* allocInstanceDataBuffer(uint16_t _num, uint16_t _stride) { -#if BGFX_CONFIG_RENDERER_OPENGLES +#if BGFX_CONFIG_RENDERER_OPENGLES2 return NULL; #else uint16_t stride = BX_ALIGN_16(_stride); diff --git a/src/config.h b/src/config.h index 433f80596..0aa814c31 100644 --- a/src/config.h +++ b/src/config.h @@ -6,21 +6,25 @@ #ifndef __CONFIG_H__ #define __CONFIG_H__ -#if !defined(BGFX_CONFIG_RENDERER_DIRECT3D) && !defined(BGFX_CONFIG_RENDERER_OPENGL) && !defined(BGFX_CONFIG_RENDERER_OPENGLES) && !defined(BGFX_CONFIG_RENDERER_NULL) -# ifndef BGFX_CONFIG_RENDERER_DIRECT3D -# define BGFX_CONFIG_RENDERER_DIRECT3D (BX_PLATFORM_WINDOWS|BX_PLATFORM_XBOX360) -# endif // BGFX_CONFIG_RENDERER_DIRECT3D +#if !defined(BGFX_CONFIG_RENDERER_DIRECT3D9) && !defined(BGFX_CONFIG_RENDERER_DIRECT3D11) && !defined(BGFX_CONFIG_RENDERER_OPENGL) && !defined(BGFX_CONFIG_RENDERER_OPENGLES2) && !defined(BGFX_CONFIG_RENDERER_NULL) +# ifndef BGFX_CONFIG_RENDERER_DIRECT3D9 +# define BGFX_CONFIG_RENDERER_DIRECT3D9 (BX_PLATFORM_WINDOWS|BX_PLATFORM_XBOX360) +# endif // BGFX_CONFIG_RENDERER_DIRECT3D9 + +# ifndef BGFX_CONFIG_RENDERER_DIRECT3D11 +# define BGFX_CONFIG_RENDERER_DIRECT3D11 0 +# endif // BGFX_CONFIG_RENDERER_DIRECT3D11 # ifndef BGFX_CONFIG_RENDERER_OPENGL # define BGFX_CONFIG_RENDERER_OPENGL (BX_PLATFORM_LINUX|BX_PLATFORM_OSX) # endif // BGFX_CONFIG_RENDERER_OPENGL -# ifndef BGFX_CONFIG_RENDERER_OPENGLES -# define BGFX_CONFIG_RENDERER_OPENGLES (BX_PLATFORM_NACL|BX_PLATFORM_ANDROID|BX_PLATFORM_IOS) +# ifndef BGFX_CONFIG_RENDERER_OPENGLES2 +# define BGFX_CONFIG_RENDERER_OPENGLES2 (BX_PLATFORM_NACL|BX_PLATFORM_ANDROID|BX_PLATFORM_IOS) # endif // BGFX_CONFIG_RENDERER_OPENGLES # ifndef BGFX_CONFIG_RENDERER_NULL -# define BGFX_CONFIG_RENDERER_NULL (!(BGFX_CONFIG_RENDERER_DIRECT3D|BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES) ) +# define BGFX_CONFIG_RENDERER_NULL (!(BGFX_CONFIG_RENDERER_DIRECT3D9|BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES2) ) # endif // BGFX_CONFIG_RENDERER_NULL #endif // !defined... diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp new file mode 100644 index 000000000..dd3e7baba --- /dev/null +++ b/src/renderer_d3d11.cpp @@ -0,0 +1,141 @@ +/* + * Copyright 2011-2012 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include "bgfx_p.h" + +#if BGFX_CONFIG_RENDERER_DIRECT3D11 + +namespace bgfx +{ + void ConstantBuffer::commit() + { + } + + void TextVideoMemBlitter::setup() + { + } + + void TextVideoMemBlitter::render(uint32_t /*_numIndices*/) + { + } + + void Context::flip() + { + } + + void Context::rendererInit() + { + } + + void Context::rendererShutdown() + { + } + + void Context::rendererCreateIndexBuffer(IndexBufferHandle /*_handle*/, Memory* /*_mem*/) + { + } + + void Context::rendererDestroyIndexBuffer(IndexBufferHandle /*_handle*/) + { + } + + void Context::rendererCreateVertexDecl(VertexDeclHandle /*_handle*/, const VertexDecl& /*_decl*/) + { + } + + void Context::rendererDestroyVertexDecl(VertexDeclHandle /*_handle*/) + { + } + + void Context::rendererCreateVertexBuffer(VertexBufferHandle /*_handle*/, Memory* /*_mem*/, VertexDeclHandle /*_declHandle*/) + { + } + + void Context::rendererDestroyVertexBuffer(VertexBufferHandle /*_handle*/) + { + } + + void Context::rendererCreateDynamicIndexBuffer(IndexBufferHandle /*_handle*/, uint32_t /*_size*/) + { + } + + void Context::rendererUpdateDynamicIndexBuffer(IndexBufferHandle /*_handle*/, uint32_t /*_offset*/, uint32_t /*_size*/, Memory* /*_mem*/) + { + } + + void Context::rendererDestroyDynamicIndexBuffer(IndexBufferHandle /*_handle*/) + { + } + + void Context::rendererCreateDynamicVertexBuffer(VertexBufferHandle /*_handle*/, uint32_t /*_size*/) + { + } + + void Context::rendererUpdateDynamicVertexBuffer(VertexBufferHandle /*_handle*/, uint32_t /*_offset*/, uint32_t /*_size*/, Memory* /*_mem*/) + { + } + + void Context::rendererDestroyDynamicVertexBuffer(VertexBufferHandle /*_handle*/) + { + } + + void Context::rendererCreateVertexShader(VertexShaderHandle /*_handle*/, Memory* /*_mem*/) + { + } + + void Context::rendererDestroyVertexShader(VertexShaderHandle /*_handle*/) + { + } + + void Context::rendererCreateFragmentShader(FragmentShaderHandle /*_handle*/, Memory* /*_mem*/) + { + } + + void Context::rendererDestroyFragmentShader(FragmentShaderHandle /*_handle*/) + { + } + + void Context::rendererCreateMaterial(MaterialHandle /*_handle*/, VertexShaderHandle /*_vsh*/, FragmentShaderHandle /*_fsh*/) + { + } + + void Context::rendererDestroyMaterial(FragmentShaderHandle /*_handle*/) + { + } + + void Context::rendererCreateTexture(TextureHandle /*_handle*/, Memory* /*_mem*/, uint32_t /*_flags*/) + { + } + + void Context::rendererDestroyTexture(TextureHandle /*_handle*/) + { + } + + void Context::rendererCreateRenderTarget(RenderTargetHandle /*_handle*/, uint16_t /*_width*/, uint16_t /*_height*/, uint32_t /*_flags*/, uint32_t /*_textureFlags*/) + { + } + + void Context::rendererDestroyRenderTarget(RenderTargetHandle /*_handle*/) + { + } + + void Context::rendererCreateUniform(UniformHandle /*_handle*/, ConstantType::Enum /*_type*/, uint16_t /*_num*/, const char* /*_name*/) + { + } + + void Context::rendererDestroyUniform(UniformHandle /*_handle*/) + { + } + + void Context::rendererSaveScreenShot(Memory* /*_mem*/) + { + } + + void Context::rendererSubmit() + { + } +} + +#endif // BGFX_CONFIG_RENDERER_DIRECT3D11 diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 66330481c..464d29ea8 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -5,7 +5,7 @@ #include "bgfx_p.h" -#if BGFX_CONFIG_RENDERER_DIRECT3D +#if BGFX_CONFIG_RENDERER_DIRECT3D9 # include "renderer_d3d9.h" namespace bgfx @@ -192,7 +192,7 @@ namespace bgfx m_D3DPERF_BeginEvent = (D3DPERF_BeginEventFunc)GetProcAddress(m_d3d9dll, "D3DPERF_BeginEvent"); m_D3DPERF_EndEvent = (D3DPERF_EndEventFunc)GetProcAddress(m_d3d9dll, "D3DPERF_EndEvent"); -#if BGFX_CONFIG_RENDERER_DIRECT3D_EX +#if BGFX_CONFIG_RENDERER_DIRECT3D9EX Direct3DCreate9ExFunc direct3DCreate9Ex = (Direct3DCreate9ExFunc)GetProcAddress(m_d3d9dll, "Direct3DCreate9Ex"); BGFX_FATAL(NULL != direct3DCreate9Ex, bgfx::Fatal::D3D9_UnableToCreateInterface, "Function Direct3DCreate9Ex not found."); direct3DCreate9Ex(D3D_SDK_VERSION, &m_d3d9); @@ -247,7 +247,7 @@ namespace bgfx for (uint32_t ii = 0; ii < countof(behaviorFlags) && NULL == m_device; ++ii) { -#if BGFX_CONFIG_RENDERER_DIRECT3D_EX +#if BGFX_CONFIG_RENDERER_DIRECT3D9EX DX_CHECK(m_d3d9->CreateDeviceEx(m_adapter , m_deviceType , g_bgfxHwnd @@ -264,7 +264,7 @@ namespace bgfx , &m_params , &m_device ) ); -#endif // BGFX_CONFIG_RENDERER_DIRECT3D_EX +#endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX } BGFX_FATAL(m_device, bgfx::Fatal::D3D9_UnableToCreateDevice, "Unable to create Direct3D9 device."); @@ -560,9 +560,9 @@ namespace bgfx { if (NULL != m_device) { -#if BGFX_CONFIG_RENDERER_DIRECT3D_EX +#if BGFX_CONFIG_RENDERER_DIRECT3D9EX DX_CHECK(m_device->WaitForVBlank(0) ); -#endif // BGFX_CONFIG_RENDERER_DIRECT3D_EX +#endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX HRESULT hr; hr = m_device->Present(NULL, NULL, NULL, NULL); @@ -694,13 +694,13 @@ namespace bgfx D3DPERF_EndEventFunc m_D3DPERF_EndEvent; #endif // BX_PLATFORM_WINDOWS -#if BGFX_CONFIG_RENDERER_DIRECT3D_EX +#if BGFX_CONFIG_RENDERER_DIRECT3D9EX IDirect3D9Ex* m_d3d9; IDirect3DDevice9Ex* m_device; #else IDirect3D9* m_d3d9; IDirect3DDevice9* m_device; -#endif // BGFX_CONFIG_RENDERER_DIRECT3D_EX +#endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX IDirect3DSurface9* m_backBufferColor; IDirect3DSurface9* m_backBufferDepthStencil; @@ -2377,6 +2377,7 @@ namespace bgfx tvm.clear(); uint16_t pos = 10; + tvm.printf(0, 0, 0x8f, " " BGFX_RENDERER_NAME " "); tvm.printf(10, pos++, 0x8e, " Frame: %3.4f [ms] / %3.2f", frameTime*toMs, freq/frameTime); tvm.printf(10, pos++, 0x8e, " Draw calls: %4d / CPU %3.4f [ms]" , m_render->m_num @@ -2415,4 +2416,4 @@ namespace bgfx } } -#endif // BGFX_CONFIG_RENDERER_DIRECT3D +#endif // BGFX_CONFIG_RENDERER_DIRECT3D9 diff --git a/src/renderer_d3d9.h b/src/renderer_d3d9.h index acfd76a17..a138fc024 100644 --- a/src/renderer_d3d9.h +++ b/src/renderer_d3d9.h @@ -6,7 +6,7 @@ #ifndef __RENDERER_D3D9_H__ #define __RENDERER_D3D9_H__ -#define BGFX_CONFIG_RENDERER_DIRECT3D_EX (BX_PLATFORM_WINDOWS && 0) +#define BGFX_CONFIG_RENDERER_DIRECT3D9EX (BX_PLATFORM_WINDOWS && 0) #ifndef D3DSTREAMSOURCE_INDEXEDDATA # define D3DSTREAMSOURCE_INDEXEDDATA (1<<30) @@ -17,16 +17,16 @@ #endif // D3DSTREAMSOURCE_INSTANCEDATA #if BX_PLATFORM_WINDOWS -# if !BGFX_CONFIG_RENDERER_DIRECT3D_EX +# if !BGFX_CONFIG_RENDERER_DIRECT3D9EX # define D3D_DISABLE_9EX -# endif // !BGFX_CONFIG_RENDERER_DIRECT3D_EX +# endif // !BGFX_CONFIG_RENDERER_DIRECT3D9EX # include -# if BGFX_CONFIG_RENDERER_DIRECT3D_EX +# if BGFX_CONFIG_RENDERER_DIRECT3D9EX typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT SDKVersion, IDirect3D9Ex**); # else typedef IDirect3D9* (WINAPI *Direct3DCreate9Func)(UINT SDKVersion); -# endif // BGFX_CONFIG_RENDERER_DIRECT3D_EX +# endif // BGFX_CONFIG_RENDERER_DIRECT3D9EX typedef int (WINAPI *D3DPERF_BeginEventFunc)(D3DCOLOR col, LPCWSTR wszName); typedef int (WINAPI *D3DPERF_EndEventFunc)(); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 07ba5a126..8cbdbb980 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -1,36 +1,36 @@ -/* - * Copyright 2011-2012 Branimir Karadzic. All rights reserved. - * License: http://www.opensource.org/licenses/BSD-2-Clause - */ - -#include "bgfx_p.h" - -#if (BGFX_CONFIG_RENDERER_OPENGLES|BGFX_CONFIG_RENDERER_OPENGL) -# include "renderer_gl.h" -# include -# include - -#if BGFX_CONFIG_RENDERER_OPENGL -# define glClearDepthf(_depth) glClearDepth(_depth) -#endif // BGFX_CONFIG_RENDERER_OPENGL - -namespace bgfx -{ -#if BGFX_USE_WGL - PFNWGLGETPROCADDRESSPROC wglGetProcAddress; - PFNWGLMAKECURRENTPROC wglMakeCurrent; - PFNWGLCREATECONTEXTPROC wglCreateContext; - PFNWGLDELETECONTEXTPROC wglDeleteContext; -#endif // BGFX_USE_WGL - -#define GL_IMPORT(_optional, _proto, _func) _proto _func -#include "glimports.h" -#undef GL_IMPORT - +/* + * Copyright 2011-2012 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include "bgfx_p.h" + +#if (BGFX_CONFIG_RENDERER_OPENGLES2|BGFX_CONFIG_RENDERER_OPENGL) +# include "renderer_gl.h" +# include +# include + +#if BGFX_CONFIG_RENDERER_OPENGL +# define glClearDepthf(_depth) glClearDepth(_depth) +#endif // BGFX_CONFIG_RENDERER_OPENGL + +namespace bgfx +{ +#if BGFX_USE_WGL + PFNWGLGETPROCADDRESSPROC wglGetProcAddress; + PFNWGLMAKECURRENTPROC wglMakeCurrent; + PFNWGLCREATECONTEXTPROC wglCreateContext; + PFNWGLDELETECONTEXTPROC wglDeleteContext; +#endif // BGFX_USE_WGL + +#define GL_IMPORT(_optional, _proto, _func) _proto _func +#include "glimports.h" +#undef GL_IMPORT + static void GL_APIENTRY stubVertexAttribDivisor(GLuint /*_index*/, GLuint /*_divisor*/) { } - + static void GL_APIENTRY stubDrawArraysInstanced(GLenum _mode, GLint _first, GLsizei _count, GLsizei /*_primcount*/) { glDrawArrays(_mode, _first, _count); @@ -41,2484 +41,2485 @@ namespace bgfx glDrawElements(_mode, _count, _type, _indices); } - static PFNGLVERTEXATTRIBDIVISORBGFXPROC s_vertexAttribDivisor = stubVertexAttribDivisor; - static PFNGLDRAWARRAYSINSTANCEDBGFXPROC s_drawArraysInstanced = stubDrawArraysInstanced; - static PFNGLDRAWELEMENTSINSTANCEDBGFXPROC s_drawElementsInstanced = stubDrawElementsInstanced; - - typedef void (*PostSwapBuffersFn)(uint32_t _width, uint32_t _height); - -#if BX_PLATFORM_NACL - void naclSwapCompleteCb(void* _data, int32_t _result); - - PP_CompletionCallback naclSwapComplete = - { - naclSwapCompleteCb, - NULL, - PP_COMPLETIONCALLBACK_FLAG_NONE - }; -#endif // BX_PLATFORM_NACL - - struct RendererContext - { - RendererContext() - : m_dxtSupport(false) - , m_flip(false) - , m_postSwapBuffers(NULL) - , m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT) -#if BX_PLATFORM_NACL - , m_context(0) - , m_instance(0) - , m_instInterface(NULL) - , m_graphicsInterface(NULL) -#elif BGFX_USE_WGL - , m_context(NULL) - , m_hdc(NULL) -#elif BGFX_USE_EGL - , m_context(NULL) - , m_display(NULL) - , m_surface(NULL) -#elif BX_PLATFORM_LINUX - , m_context(0) - , m_window(0) - , m_display(NULL) -#endif // BX_PLATFORM_ - { - memset(&m_resolution, 0, sizeof(m_resolution) ); - } - - void updateResolution(const Resolution& _resolution) - { - if (m_resolution.m_width != _resolution.m_width - || m_resolution.m_height != _resolution.m_height - || m_resolution.m_flags != _resolution.m_flags) - { - m_textVideoMem.resize(false, _resolution.m_width, _resolution.m_height); - m_textVideoMem.clear(); - - m_resolution = _resolution; - setRenderContextSize(_resolution.m_width, _resolution.m_height); - } - } - - void setRenderContextSize(uint32_t _width, uint32_t _height) - { - if (_width != 0 - || _height != 0) - { -#if BX_PLATFORM_NACL - if (0 == m_context) - { - BX_TRACE("create context"); - - int32_t attribs[] = - { - PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, - PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, - PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, - PP_GRAPHICS3DATTRIB_SAMPLES, 0, - PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, - PP_GRAPHICS3DATTRIB_WIDTH, _width, - PP_GRAPHICS3DATTRIB_HEIGHT, _height, - PP_GRAPHICS3DATTRIB_NONE - }; - - m_context = m_graphicsInterface->Create(m_instance, 0, attribs); - m_instInterface->BindGraphics(m_instance, m_context); - glSetCurrentContextPPAPI(m_context); - m_graphicsInterface->SwapBuffers(m_context, naclSwapComplete); - -#if 0 - # define GL_IMPORT(_optional, _proto, _func) \ - { \ - _func = (_proto)eglGetProcAddress(#_func); \ - BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGL context. eglGetProcAddress(\"%s\")", #_func); \ - } - # include "glimports.h" - # undef GL_IMPORT -#endif - } - else - { - m_graphicsInterface->ResizeBuffers(m_context, _width, _height); - } - -#elif BGFX_USE_WGL - if (NULL == m_hdc) - { - m_opengl32dll = LoadLibrary("opengl32.dll"); - BGFX_FATAL(NULL != m_opengl32dll, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to load opengl32.dll."); - - wglGetProcAddress = (PFNWGLGETPROCADDRESSPROC)GetProcAddress(m_opengl32dll, "wglGetProcAddress"); - BGFX_FATAL(NULL != wglGetProcAddress, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglGetProcAddress."); - - wglMakeCurrent = (PFNWGLMAKECURRENTPROC)GetProcAddress(m_opengl32dll, "wglMakeCurrent"); - BGFX_FATAL(NULL != wglMakeCurrent, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglMakeCurrent."); - - wglCreateContext = (PFNWGLCREATECONTEXTPROC)GetProcAddress(m_opengl32dll, "wglCreateContext"); - BGFX_FATAL(NULL != wglCreateContext, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglCreateContext."); - - wglDeleteContext = (PFNWGLDELETECONTEXTPROC)GetProcAddress(m_opengl32dll, "wglDeleteContext"); - BGFX_FATAL(NULL != wglDeleteContext, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglDeleteContext."); - - m_hdc = GetDC(g_bgfxHwnd); - BGFX_FATAL(NULL != m_hdc, bgfx::Fatal::OPENGL_UnableToCreateContext, "GetDC failed!"); - - PIXELFORMATDESCRIPTOR pfd; - memset(&pfd, 0, sizeof(pfd) ); - pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); - pfd.nVersion = 1; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 32; - pfd.cAlphaBits = 8; - pfd.cDepthBits = 24; - pfd.cStencilBits = 8; - pfd.iLayerType = PFD_MAIN_PLANE; - - int pixelFormat = ChoosePixelFormat(m_hdc, &pfd); - BGFX_FATAL(0 != pixelFormat, bgfx::Fatal::OPENGL_UnableToCreateContext, "ChoosePixelFormat failed!"); - - DescribePixelFormat(m_hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); - - int result; - result = SetPixelFormat(m_hdc, pixelFormat, &pfd); - BGFX_FATAL(0 != result, bgfx::Fatal::OPENGL_UnableToCreateContext, "SetPixelFormat failed!"); - - m_context = wglCreateContext(m_hdc); - BGFX_FATAL(NULL != m_context, bgfx::Fatal::OPENGL_UnableToCreateContext, "wglCreateContext failed!"); - - result = wglMakeCurrent(m_hdc, m_context); - BGFX_FATAL(0 != result, bgfx::Fatal::OPENGL_UnableToCreateContext, "wglMakeCurrent failed!"); - -# define GL_IMPORT(_optional, _proto, _func) \ - { \ - _func = (_proto)wglGetProcAddress(#_func); \ - if (_func == NULL) \ - { \ - _func = (_proto)GetProcAddress(m_opengl32dll, #_func); \ - } \ - BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGL context. wglGetProcAddress(\"%s\")", #_func); \ - } -# include "glimports.h" -# undef GL_IMPORT - } -#elif BX_PLATFORM_LINUX - - if (0 == m_display) - { - Display* display = XOpenDisplay(0); - XLockDisplay(display); - BGFX_FATAL(display, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to open X display (0)."); - - int glxMajor, glxMinor; - if (!glXQueryVersion(display, &glxMajor, &glxMinor)) - { - BGFX_FATAL(false, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to query GLX version"); - } - BGFX_FATAL((glxMajor == 1 && glxMinor >= 3) || glxMajor > 1, bgfx::Fatal::OPENGL_UnableToCreateContext, "GLX version is not >=1.3 (%d.%d).", glxMajor, glxMinor); - - const int glxAttribs[] = - { - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, True, - None, - }; - - // Find suitable config - GLXFBConfig bestconfig = NULL; - - int nconfigs; - GLXFBConfig* configs = glXChooseFBConfig(display, DefaultScreen(display), glxAttribs, &nconfigs); - - XVisualInfo* visualInfo = 0; - for (int ii = 0; ii < nconfigs; ++ii) - { - visualInfo = glXGetVisualFromFBConfig(display, configs[ii]); - if (visualInfo) - { - // Check if meets min spec - bool validconfig = true; - for (uint32_t attridx = 0; attridx < countof(glxAttribs)-1 && glxAttribs[attridx] != None; attridx += 2) - { - int value; - glXGetFBConfigAttrib(display, configs[ii], glxAttribs[attridx], &value); - if (value < glxAttribs[attridx + 1]) - { - validconfig = false; - break; - } - } - - if (validconfig) - { - bestconfig = configs[ii]; - break; - } - } - - XFree(visualInfo); - visualInfo = 0; - } - - XFree(configs); - BGFX_FATAL(visualInfo, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to find a suitable X11 display configuration."); - - // Generate colormaps - XSetWindowAttributes windowAttrs; - windowAttrs.colormap = XCreateColormap(display, RootWindow(display, visualInfo->screen), visualInfo->visual, AllocNone); - windowAttrs.background_pixmap = None; - windowAttrs.border_pixel = 0; - - Window window = XCreateWindow( - display - , RootWindow(display, visualInfo->screen) - , 0, 0 - , _width, _height, 0, visualInfo->depth - , InputOutput - , visualInfo->visual - , CWBorderPixel|CWColormap - , &windowAttrs - ); - BGFX_FATAL(window, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create X11 window."); - - XMapRaised(display, window); - XFlush(display); - XFree(visualInfo); - - BX_TRACE("create context"); - - typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); - glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); - BGFX_FATAL(glXCreateContextAttribsARB, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to get glXCreateContextAttribsARB."); - - const int contextArrib[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - None, - }; - - m_context = glXCreateContextAttribsARB(display, bestconfig, 0, True, contextArrib); - BGFX_FATAL(m_context, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create GLX context."); - - glXMakeCurrent(display, window, m_context); - -# define GL_IMPORT(_optional, _proto, _func) \ - { \ - _func = (_proto)glXGetProcAddress((const GLubyte*)#_func); \ - BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGL context. glXGetProcAddress %s", #_func); \ - } -# include "glimports.h" -# undef GL_IMPORT - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - glXSwapBuffers(display, window); - - m_display = display; - m_window = window; - XUnlockDisplay(display); - } - else - { - XResizeWindow(m_display, m_window, _width, _height); - } -#elif BGFX_USE_EGL - if (NULL == m_context) - { - m_display = eglGetDisplay(NULL); - BGFX_FATAL(m_display != EGL_NO_DISPLAY, Fatal::OPENGL_UnableToCreateContext, "Failed to create display 0x%08x", m_display); - - EGLint major = 0; - EGLint minor = 0; - EGLBoolean success = eglInitialize(m_display, &major, &minor); - BGFX_FATAL(success && major >= 1 && minor >= 4, Fatal::OPENGL_UnableToCreateContext, "Failed to initialize %d.%d", major, minor); - - EGLint attrs[] = - { -# if BX_PLATFORM_ANDROID - EGL_DEPTH_SIZE, 16, -# else - EGL_DEPTH_SIZE, 24, -# endif // BX_PLATFORM_ - - EGL_NONE - }; - EGLint numConfig = 0; - EGLConfig config = 0; - success = eglChooseConfig(m_display, attrs, &config, 1, &numConfig); - BGFX_FATAL(success, Fatal::OPENGL_UnableToCreateContext, "eglChooseConfig"); - - m_surface = eglCreateWindowSurface(m_display, config, (EGLNativeWindowType)g_bgfxHwnd, NULL); - BGFX_FATAL(m_surface != EGL_NO_SURFACE, Fatal::OPENGL_UnableToCreateContext, "Failed to create surface."); - - m_context = eglCreateContext(m_display, config, EGL_NO_CONTEXT, NULL); - BGFX_FATAL(m_context != EGL_NO_CONTEXT, Fatal::OPENGL_UnableToCreateContext, "Failed to create context."); - - success = eglMakeCurrent(m_display, m_surface, m_surface, m_context); - BGFX_FATAL(success, Fatal::OPENGL_UnableToCreateContext, "Failed to set context."); - -# define GL_IMPORT(_optional, _proto, _func) \ - { \ - _func = (_proto)eglGetProcAddress(#_func); \ - BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGLES context. eglGetProcAddress(\"%s\")", #_func); \ - } -# include "glimports.h" -# undef GL_IMPORT - } -#endif // BX_PLATFORM_ - } - - if (NULL != glVertexAttribDivisor - && NULL != glDrawArraysInstanced - && NULL != glDrawElementsInstanced) - { - s_vertexAttribDivisor = glVertexAttribDivisor; - s_drawArraysInstanced = glDrawArraysInstanced; - s_drawElementsInstanced = glDrawElementsInstanced; - } - else - { - s_vertexAttribDivisor = stubVertexAttribDivisor; - s_drawArraysInstanced = stubDrawArraysInstanced; - s_drawElementsInstanced = stubDrawElementsInstanced; - } - - m_flip = true; - } - - void flip() - { - if (m_flip) - { -#if BX_PLATFORM_NACL - glSetCurrentContextPPAPI(m_context); - m_graphicsInterface->SwapBuffers(m_context, naclSwapComplete); -#elif BGFX_USE_WGL - wglMakeCurrent(m_hdc, m_context); - SwapBuffers(m_hdc); -#elif BGFX_USE_EGL - eglMakeCurrent(m_display, m_surface, m_surface, m_context); - eglSwapBuffers(m_display, m_surface); -#elif BX_PLATFORM_LINUX - glXSwapBuffers(m_display, m_window); -#endif // BX_PLATFORM_ - } - - if (NULL != m_postSwapBuffers) - { - m_postSwapBuffers(m_resolution.m_width, m_resolution.m_height); - } - } - - void saveScreenShot(Memory* _mem) - { -#if BGFX_CONFIG_RENDERER_OPENGL - void* data = g_realloc(NULL, m_resolution.m_width*m_resolution.m_height*4); - glReadPixels(0, 0, m_resolution.m_width, m_resolution.m_height, GL_RGBA, GL_UNSIGNED_BYTE, data); - - uint8_t* rgba = (uint8_t*)data; - for (uint32_t ii = 0, num = m_resolution.m_width*m_resolution.m_height; ii < num; ++ii) - { - uint8_t temp = rgba[0]; - rgba[0] = rgba[2]; - rgba[2] = temp; - rgba += 4; - } - - saveTga( (const char*)_mem->data, m_resolution.m_width, m_resolution.m_height, m_resolution.m_width*4, data, false, true); - g_free(data); -#endif // BGFX_CONFIG_RENDERER_OPENGL - } - - void init() - { - setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT); -#if BGFX_CONFIG_RENDERER_OPENGL - m_queries.create(); -#endif // BGFX_CONFIG_RENDERER_OPENGL - } - - void shutdown() - { -#if BGFX_CONFIG_RENDERER_OPENGL - m_queries.destroy(); -#endif // BGFX_CONFIG_RENDERER_OPENGL - -#if BGFX_USE_WGL - if (NULL != m_hdc) - { - wglMakeCurrent(NULL, NULL); - wglDeleteContext(m_context); - m_context = NULL; - } - - FreeLibrary(m_opengl32dll); -#elif BGFX_USE_EGL - eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(m_display, m_context); - eglDestroySurface(m_display, m_surface); - eglTerminate(m_display); - m_context = NULL; -#endif // BGFX_USE_ - } - - IndexBuffer m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS]; - VertexBuffer m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS]; - Shader m_vertexShaders[BGFX_CONFIG_MAX_VERTEX_SHADERS]; - Shader m_fragmentShaders[BGFX_CONFIG_MAX_FRAGMENT_SHADERS]; - Material m_materials[BGFX_CONFIG_MAX_MATERIALS]; - Texture m_textures[BGFX_CONFIG_MAX_TEXTURES]; - VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS]; - RenderTarget m_renderTargets[BGFX_CONFIG_MAX_RENDER_TARGETS]; - UniformRegistry m_uniformReg; - void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; -#if BGFX_CONFIG_RENDERER_OPENGL - Queries m_queries; -#endif // BGFX_CONFIG_RENDERER_OPENGL - - TextVideoMem m_textVideoMem; - - Resolution m_resolution; - bool m_dxtSupport; - bool m_flip; - - PostSwapBuffersFn m_postSwapBuffers; - uint64_t m_hash; - -#if BX_PLATFORM_NACL - PP_Resource m_context; - PP_Instance m_instance; - const PPB_Instance* m_instInterface; - const PPB_Graphics3D* m_graphicsInterface; -#elif BGFX_USE_WGL - HMODULE m_opengl32dll; - HGLRC m_context; - HDC m_hdc; -#elif BGFX_USE_EGL - EGLContext m_context; - EGLDisplay m_display; - EGLSurface m_surface; -#elif BX_PLATFORM_LINUX - GLXContext m_context; - Window m_window; - Display* m_display; -#endif // BX_PLATFORM_NACL - }; - - RendererContext s_renderCtx; - -#if BX_PLATFORM_NACL - void naclSetIntefraces(PP_Instance _instance, const PPB_Instance* _instInterface, const PPB_Graphics3D* _graphicsInterface, PostSwapBuffersFn _postSwapBuffers) - { - s_renderCtx.m_instance = _instance; - s_renderCtx.m_instInterface = _instInterface; - s_renderCtx.m_graphicsInterface = _graphicsInterface; - s_renderCtx.m_postSwapBuffers = _postSwapBuffers; - s_renderCtx.setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT); - } - - void naclSwapCompleteCb(void* /*_data*/, int32_t /*_result*/) - { - renderFrame(); - } - -#elif BX_PLATFORM_LINUX - bool linuxGetDisplay(Display** _display, Window* _window) - { - if (!s_renderCtx.m_display) - { - return false; - } - - *_display = s_renderCtx.m_display; - *_window = s_renderCtx.m_window; - return true; - } -#endif // BX_PLATFORM_ - - struct Extension - { - enum Enum - { - EXT_texture_format_BGRA8888, - EXT_texture_compression_s3tc, - EXT_texture_compression_dxt1, - CHROMIUM_texture_compression_dxt3, - CHROMIUM_texture_compression_dxt5, - OES_standard_derivatives, - ARB_get_program_binary, - OES_get_program_binary, - EXT_framebuffer_blit, - ARB_timer_query, - EXT_timer_query, - EXT_texture_sRGB, - ARB_framebuffer_sRGB, - EXT_framebuffer_sRGB, - ARB_multisample, - CHROMIUM_framebuffer_multisample, - ANGLE_translated_shader_source, - ARB_instanced_arrays, - ANGLE_instanced_arrays, - OES_texture_float, - OES_texture_float_linear, - OES_texture_half_float, - OES_texture_half_float_linear, - EXT_occlusion_query_boolean, - - Count - }; - - const char* m_name; - bool m_supported; - bool m_initialize; - }; - - static Extension s_extension[Extension::Count] = - { - // Nvidia BGRA on Linux bug: - // https://groups.google.com/a/chromium.org/forum/?fromgroups#!topic/chromium-reviews/yFfbUdyeUCQ - { "GL_EXT_texture_format_BGRA8888", false, !BX_PLATFORM_LINUX }, - { "GL_EXT_texture_compression_s3tc", false, true }, - { "GL_EXT_texture_compression_dxt1", false, true }, - { "GL_CHROMIUM_texture_compression_dxt3", false, true }, - { "GL_CHROMIUM_texture_compression_dxt5", false, true }, - { "GL_OES_standard_derivatives", false, true }, - { "GL_ARB_get_program_binary", false, true }, - { "GL_OES_get_program_binary", false, false }, - { "GL_EXT_framebuffer_blit", false, true }, - { "GL_ARB_timer_query", false, true }, - { "GL_EXT_timer_query", false, true }, - { "GL_EXT_texture_sRGB", false, true }, - { "GL_ARB_framebuffer_sRGB", false, true }, - { "GL_EXT_framebuffer_sRGB", false, true }, - { "GL_ARB_multisample", false, true }, - { "GL_CHROMIUM_framebuffer_multisample", false, true }, - { "GL_ANGLE_translated_shader_source", false, true }, - { "GL_ARB_instanced_arrays", false, true }, - { "GL_ANGLE_instanced_arrays", false, true }, - { "GL_OES_texture_float", false, true }, - { "GL_OES_texture_float_linear", false, true }, - { "GL_OES_texture_half_float", false, true }, - { "GL_OES_texture_half_float_linear", false, true }, - { "GL_EXT_occlusion_query_boolean", false, true }, - }; - - static const GLenum s_primType[] = - { - GL_TRIANGLES, - GL_LINES, - GL_POINTS, - }; - - static const uint32_t s_primNumVerts[] = - { - 3, - 2, - 1, - }; - - static const char* s_attribName[Attrib::Count] = - { - "a_position", - "a_normal", - "a_color", - "a_color1", - "a_indices", - "a_weight", - "a_texcoord0", - "a_texcoord1", - "a_texcoord2", - "a_texcoord3", - "a_texcoord4", - "a_texcoord5", - "a_texcoord6", - "a_texcoord7", - }; - - static const char* s_instanceDataName[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT] = - { - "i_data0", - "i_data1", - "i_data2", - "i_data3", - "i_data4", - }; - - static const GLenum s_attribType[AttribType::Count] = - { - GL_UNSIGNED_BYTE, - GL_UNSIGNED_SHORT, - GL_FLOAT, - }; - - static const GLenum s_blendFactor[] = - { - 0, // ignored - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA_SATURATE, - }; - - static const GLenum s_depthFunc[] = - { - 0, // ignored - GL_LESS, - GL_LEQUAL, - GL_EQUAL, - GL_GEQUAL, - GL_GREATER, - GL_NOTEQUAL, - GL_NEVER, - GL_ALWAYS, - }; - - // Specifies the internal format of the texture. - // Must be one of the following symbolic constants: - // GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA. - static const GLenum s_colorFormat[] = - { - 0, // ignored - GL_RGBA, - GL_RGBA, - }; - - static const GLenum s_depthFormat[] = - { - 0, // ignored - 0, - }; - - static const GLenum s_textureAddress[] = - { - GL_REPEAT, - GL_MIRRORED_REPEAT, - GL_CLAMP_TO_EDGE, - }; - - static const GLenum s_textureFilter[] = - { - GL_LINEAR, - GL_NEAREST, - }; - - struct TextureFormatInfo - { - GLenum m_internalFmt; - GLenum m_format; - GLenum m_type; - uint8_t m_bpp; - }; - - static const TextureFormatInfo s_textureFormat[TextureFormat::Count] = - { - { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, GL_ZERO, 1 }, - { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, GL_ZERO, 1 }, - { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, GL_ZERO, 1 }, - { GL_ZERO, GL_ZERO, GL_ZERO, 0 }, - { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, -#if BGFX_CONFIG_RENDERER_OPENGL - { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, 8 }, -#else - { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 8 }, -#endif // BGFX_CONFIG_RENDERER_OPENGL - }; - - const char* glslTypeName(GLuint _type) - { -#define GLSL_TYPE(_ty) case _ty: return #_ty - - switch (_type) - { - GLSL_TYPE(GL_FLOAT); - GLSL_TYPE(GL_FLOAT_VEC2); - GLSL_TYPE(GL_FLOAT_VEC3); - GLSL_TYPE(GL_FLOAT_VEC4); - GLSL_TYPE(GL_FLOAT_MAT2); - GLSL_TYPE(GL_FLOAT_MAT3); - GLSL_TYPE(GL_FLOAT_MAT4); -// GLSL_TYPE(GL_FLOAT_MAT2x3); -// GLSL_TYPE(GL_FLOAT_MAT2x4); -// GLSL_TYPE(GL_FLOAT_MAT3x2); -// GLSL_TYPE(GL_FLOAT_MAT3x4); -// GLSL_TYPE(GL_FLOAT_MAT4x2); -// GLSL_TYPE(GL_FLOAT_MAT4x3); -// GLSL_TYPE(GL_SAMPLER_1D); - GLSL_TYPE(GL_SAMPLER_2D); -// GLSL_TYPE(GL_SAMPLER_3D); - GLSL_TYPE(GL_SAMPLER_CUBE); -// GLSL_TYPE(GL_SAMPLER_1D_SHADOW); -// GLSL_TYPE(GL_SAMPLER_2D_SHADOW); - } - -#undef GLSL_TYPE - - return "UNKNOWN GLSL TYPE!"; - } - - const char* glEnumName(GLenum _enum) - { -#define GLENUM(_ty) case _ty: return #_ty - - switch (_enum) - { - GLENUM(GL_TEXTURE); - GLENUM(GL_RENDERBUFFER); - } - -#undef GLENUM - - return "UNKNOWN GLENUM!"; - } - - ConstantType::Enum convertGlType(GLenum _type) - { - switch (_type) - { - case GL_FLOAT: - return ConstantType::Uniform1fv; - - case GL_FLOAT_VEC2: - return ConstantType::Uniform2fv; - - case GL_FLOAT_VEC3: - return ConstantType::Uniform3fv; - - case GL_FLOAT_VEC4: - return ConstantType::Uniform4fv; - - case GL_FLOAT_MAT2: - break; - - case GL_FLOAT_MAT3: - return ConstantType::Uniform3x3fv; - - case GL_FLOAT_MAT4: - return ConstantType::Uniform4x4fv; - -// case GL_FLOAT_MAT2x3: -// case GL_FLOAT_MAT2x4: -// case GL_FLOAT_MAT3x2: -// case GL_FLOAT_MAT3x4: -// case GL_FLOAT_MAT4x2: -// case GL_FLOAT_MAT4x3: -// break; - - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: -// case GL_SAMPLER_1D: -// case GL_SAMPLER_3D: -// case GL_SAMPLER_1D_SHADOW: -// case GL_SAMPLER_2D_SHADOW: - return ConstantType::Uniform1iv; - }; - - return ConstantType::End; - } - - void Material::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); - - bool cached = false; - -#if BGFX_CONFIG_RENDERER_OPENGL - uint64_t id = (uint64_t(_vsh.m_hash)<<32) | _fsh.m_hash; - id ^= s_renderCtx.m_hash; - - if (s_extension[Extension::ARB_get_program_binary].m_supported) - { - uint32_t length; - g_cache(id, false, NULL, length); - cached = length > 0; - - if (cached) - { - void* data = g_realloc(NULL, length); - g_cache(id, false, data, length); - - StreamRead stream(data, length); - - GLenum format; - stream.read(format); - - GL_CHECK(glProgramBinary(m_id, format, stream.getDataPtr(), stream.remaining() ) ); - - g_free(data); - } - else - { - GL_CHECK(glProgramParameteri(m_id, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE) ); - } - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - - if (!cached) - { - 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; - } - -#if BGFX_CONFIG_RENDERER_OPENGL - if (s_extension[Extension::ARB_get_program_binary].m_supported) - { - GLint programLength; - GLenum format; - GL_CHECK(glGetProgramiv(m_id, GL_PROGRAM_BINARY_LENGTH, &programLength) ); - - uint32_t length = programLength + 4; - uint8_t* data = (uint8_t*)g_realloc(NULL, length); - GL_CHECK(glGetProgramBinary(m_id, programLength, NULL, &format, &data[4]) ); - *(uint32_t*)data = format; - - g_cache(id, true, data, length); - - g_free(data); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - } - - init(); - } - - void Material::destroy() - { - GL_CHECK(glUseProgram(0) ); - GL_CHECK(glDeleteProgram(m_id) ); - } - - void Material::init() - { - GLint activeAttribs; - GLint activeUniforms; - - GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_ATTRIBUTES, &activeAttribs) ); - GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_UNIFORMS, &activeUniforms) ); - - GLint max0, max1; - GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max0) ); - GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max1) ); - - GLint maxLength = uint32_max(max0, max1); - char* name = (char*)g_realloc(NULL, maxLength + 1); - - BX_TRACE("Program %d", m_id); - BX_TRACE("Attributes:"); - for (int32_t ii = 0; ii < activeAttribs; ++ii) - { - GLint size; - GLenum type; - - GL_CHECK(glGetActiveAttrib(m_id, ii, maxLength + 1, NULL, &size, &type, name) ); - BX_TRACE("\t%s %s is at location %d" - , glslTypeName(type) - , name - , glGetAttribLocation(m_id, name) - ); - } - - m_numPredefined = 0; - m_constantBuffer = ConstantBuffer::create(1024); - m_numSamplers = 0; - - BX_TRACE("Uniforms:"); - for (int32_t ii = 0; ii < activeUniforms; ++ii) - { - GLint num; - GLenum gltype; - - GL_CHECK(glGetActiveUniform(m_id, ii, maxLength + 1, NULL, &num, &gltype, name) ); - GLint loc = glGetUniformLocation(m_id, name); - - int offset = 0; - char* array = strchr(name, '['); - if (NULL != array) - { - BX_TRACE("--- %s", name); - *array = '\0'; - array++; - char* end = strchr(array, ']'); - *end = '\0'; - offset = atoi(array); - } - - if (GL_SAMPLER_2D == gltype) - { - BX_TRACE("Sampler %d at %d.", m_numSamplers, loc); - m_sampler[m_numSamplers] = loc; - m_numSamplers++; - } - - const void* data = NULL; - PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); - if (PredefinedUniform::Count != predefined) - { - m_predefined[m_numPredefined].m_loc = loc; - m_predefined[m_numPredefined].m_type = predefined; - m_predefined[m_numPredefined].m_count = num; - m_numPredefined++; - } - else - { - const UniformInfo* info = s_renderCtx.m_uniformReg.find(name); - if (NULL != info) - { - data = info->m_data; - ConstantType::Enum type = convertGlType(gltype); - m_constantBuffer->writeUniformRef(type, loc, data, num); - BX_TRACE("store %s %p", name, data); - } - } - - BX_TRACE("\tuniform %s %s%s is at location %d, size %d (%p), offset %d" - , glslTypeName(gltype) - , name - , PredefinedUniform::Count != predefined ? "*" : "" - , loc - , num - , data - , offset - ); - BX_UNUSED(offset); - } - - m_constantBuffer->finish(); - - g_free(name); - - memset(m_attributes, 0xff, sizeof(m_attributes) ); - uint32_t used = 0; - for (uint32_t ii = 0; ii < Attrib::Count; ++ii) - { - GLuint loc = glGetAttribLocation(m_id, s_attribName[ii]); - if (GLuint(-1) != loc ) - { - BX_TRACE("attr %s: %d", s_attribName[ii], loc); - m_attributes[ii] = loc; - m_used[used++] = ii; - } - } - m_used[used] = Attrib::Count; - - used = 0; - for (uint32_t ii = 0; ii < countof(s_instanceDataName); ++ii) - { - GLuint loc = glGetAttribLocation(m_id, s_instanceDataName[ii]); - if (GLuint(-1) != loc ) - { - BX_TRACE("instance data %s: %d", s_instanceDataName[ii], loc); - m_instanceData[used++] = loc; - } - } - m_instanceData[used] = 0xffff; - } - - void Material::bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex) const - { - uint32_t enabled = 0; - for (uint32_t ii = 0; Attrib::Count != m_used[ii]; ++ii) - { - Attrib::Enum attr = Attrib::Enum(m_used[ii]); - GLuint loc = m_attributes[attr]; - - uint8_t num; - AttribType::Enum type; - bool normalized; - _vertexDecl.decode(attr, num, type, normalized); - - if (0xffff != loc - && 0xff != _vertexDecl.m_attributes[attr]) - { - GL_CHECK(glEnableVertexAttribArray(loc) ); - enabled |= 1< 1) - { - m_target = GL_TEXTURE_3D; - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - else - { - m_target = GL_TEXTURE_2D; - } - - GL_CHECK(glGenTextures(1, &m_id) ); - BX_CHECK(0 != m_id, "Failed to generate texture id."); - GL_CHECK(glBindTexture(m_target, m_id) ); - - const TextureFormatInfo& tfi = s_textureFormat[dds.m_type]; - GLenum internalFmt = tfi.m_internalFmt; - GLenum fmt = tfi.m_format; - - GLenum target = m_target; - if (dds.m_cubeMap) - { - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - } - - if (!s_renderCtx.m_dxtSupport - || TextureFormat::Unknown < dds.m_type) - { - if (GL_RGBA == internalFmt) - { - internalFmt = s_extension[Extension::EXT_texture_format_BGRA8888].m_supported ? GL_BGRA_EXT : GL_RGBA; - fmt = internalFmt; - } - - uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*tfi.m_bpp); - - for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = dds.m_width; - uint32_t height = dds.m_height; - uint32_t depth = dds.m_depth; - - for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod) - { - width = uint32_max(1, width); - height = uint32_max(1, height); - depth = uint32_max(1, depth); - - Mip mip; - if (getRawImageData(dds, 0, lod, _mem, mip) ) - { - mip.decode(bits); - - if (GL_RGBA == internalFmt) - { - uint32_t dstpitch = width*4; - for (uint32_t yy = 0; yy < height; ++yy) - { - uint8_t* dst = &bits[yy*dstpitch]; - - for (uint32_t xx = 0; xx < width; ++xx) - { - uint8_t tmp = dst[0]; - dst[0] = dst[2]; - dst[2] = tmp; - dst += 4; - } - } - } - -#if BGFX_CONFIG_RENDERER_OPENGL - if (target == GL_TEXTURE_3D) - { - GL_CHECK(glTexImage3D(target - , lod - , internalFmt - , width - , height - , depth - , 0 - , fmt - , tfi.m_type - , bits - ) ); - } - else -#endif // BGFX_CONFIG_RENDERER_OPENGL - { - GL_CHECK(glTexImage2D(target+side - , lod - , internalFmt - , width - , height - , 0 - , fmt - , tfi.m_type - , bits - ) ); - } - } - - width >>= 1; - height >>= 1; - depth >>= 1; - } - } - - g_free(bits); - } - else - { - for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side) - { - uint32_t width = dds.m_width; - uint32_t height = dds.m_height; - uint32_t depth = dds.m_depth; - - for (uint32_t ii = 0, num = dds.m_numMips; ii < num; ++ii) - { - width = uint32_max(1, width); - height = uint32_max(1, height); - depth = uint32_max(1, depth); - - Mip mip; - if (getRawImageData(dds, 0, ii, _mem, mip) ) - { -#if BGFX_CONFIG_RENDERER_OPENGL - if (m_target == GL_TEXTURE_3D) - { - GL_CHECK(glCompressedTexImage3D(target - , ii - , internalFmt - , width - , height - , depth - , 0 - , mip.m_size - , mip.m_data - ) ); - } - else -#endif // BGFX_CONFIG_RENDERER_OPENGL - { - GL_CHECK(glCompressedTexImage2D(target+side - , ii - , internalFmt - , width - , height - , 0 - , mip.m_size - , mip.m_data - ) ); - } - } - - width >>= 1; - height >>= 1; - depth >>= 1; - } - } - } - - } - else - { - m_target = GL_TEXTURE_2D; - GL_CHECK(glGenTextures(1, &m_id) ); - BX_CHECK(0 != m_id, "Failed to generate texture id."); - GL_CHECK(glBindTexture(m_target, m_id) ); - - StreamRead stream(_mem->data, _mem->size); - - uint32_t magic; - stream.read(magic); - - if (BGFX_MAGIC == magic) - { - uint16_t width; - stream.read(width); - - uint16_t height; - stream.read(height); - - uint8_t bpp; - stream.read(bpp); - - stream.read(numMips); - - stream.align(16); - - for (uint8_t mip = 0; mip < numMips; ++mip) - { - width = uint32_max(width, 1); - height = uint32_max(height, 1); - - const uint8_t* data = stream.getDataPtr(); - stream.skip(width*height*bpp); - - GL_CHECK(glTexImage2D(m_target - , mip - , 1 == bpp ? GL_LUMINANCE : GL_RGBA - , width - , height - , 0 - , 1 == bpp ? GL_LUMINANCE : GL_RGBA - , GL_UNSIGNED_BYTE - , data - ) ); - - width >>= 1; - height >>= 1; - } - } - else - { - // - } - } - - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]) ); - -#if BGFX_CONFIG_RENDERER_OPENGL - if (m_target == GL_TEXTURE_3D) - { - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_R, s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]) ); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, 1 < numMips ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) ); - - GL_CHECK(glBindTexture(m_target, 0) ); - } - - void Texture::createColor(uint32_t _width, uint32_t _height, GLenum _min, GLenum _mag) - { - GLenum internalFormat = /*_fp ? GL_RGBA16F_ARB :*/ GL_RGBA; - GLenum type = /*_fp ? GL_HALF_FLOAT_ARB :*/ GL_UNSIGNED_BYTE; - m_target = /*0 != _depth ? GL_TEXTURE_3D :*/ GL_TEXTURE_2D; - - GL_CHECK(glGenTextures(1, &m_id) ); - BX_CHECK(0 != m_id, "Failed to generate texture id."); - GL_CHECK(glBindTexture(m_target, m_id) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, _min) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, _mag) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) ); - - GL_CHECK(glTexImage2D(m_target - , 0 - , internalFormat - , _width - , _height - , 0 - , GL_RGBA - , type - , NULL - ) ); - - GL_CHECK(glBindTexture(m_target, 0) ); - } - - void Texture::createDepth(uint32_t _width, uint32_t _height) - { - m_target = GL_TEXTURE_2D; - - GL_CHECK(glGenTextures(1, &m_id) ); - BX_CHECK(0 != m_id, "Failed to generate texture id."); - GL_CHECK(glBindTexture(m_target, m_id) ); -// glTexParameteri(m_target, GL_TEXTURE_COMPARE_MODE, GL_NONE); -// glTexParameteri(m_target, GL_DEPTH_TEXTURE_MODE, GL_NONE); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ); - GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) ); - - // OpenGL ES 2.0 doesn't support GL_DEPTH_COMPONENT... this will fail. - GL_CHECK(glTexImage2D(m_target - , 0 - , GL_DEPTH_COMPONENT - , _width - , _height - , 0 - , GL_DEPTH_COMPONENT - , GL_FLOAT - , NULL - ) ); - - GL_CHECK(glBindTexture(m_target, 0) ); - } - - void Texture::destroy() - { - if (0 != m_id) - { - GL_CHECK(glBindTexture(m_target, 0) ); - GL_CHECK(glDeleteTextures(1, &m_id) ); - m_id = 0; - } - } - - void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) - { - BX_TRACE("Create render target %dx%d 0x%02x", _width, _height, _flags); - - m_width = _width; - m_height = _height; - -// m_msaa = s_msaa[(m_flags&BGFX_RENDER_TARGET_MSAA_MASK)>>BGFX_RENDER_TARGET_MSAA_SHIFT]; - uint32_t colorFormat = (_flags&BGFX_RENDER_TARGET_COLOR_MASK)>>BGFX_RENDER_TARGET_COLOR_SHIFT; - uint32_t depthFormat = (_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; - GLenum minFilter = s_textureFilter[(_textureFlags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; - GLenum magFilter = s_textureFilter[(_textureFlags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; - - if (0 < colorFormat) - { - m_color.createColor(_width, _height, minFilter, magFilter); - } - -#if 0 // GLES can't create texture with depth texture format... - if (0 < depthFormat) - { - m_depth.createDepth(_width, _height); - } -#endif // - - GL_CHECK(glGenFramebuffers(1, &m_fbo) ); - BX_CHECK(0 != m_fbo, "Failed to generate framebuffer id."); - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) ); - - if (0 < colorFormat) - { - GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER - , GL_COLOR_ATTACHMENT0 - , m_color.m_target - , m_color.m_id - , 0 - ) ); - } - - if (0 < depthFormat) - { - if (0 < colorFormat) - { -#if BGFX_CONFIG_RENDERER_OPENGL - GLenum depthComponent = GL_DEPTH_COMPONENT32; -#else - GLenum depthComponent = GL_DEPTH_COMPONENT16; -#endif // BGFX_CONFIG_RENDERER_OPENGL - - GL_CHECK(glGenRenderbuffers(1, &m_rbo) ); - BX_CHECK(0 != m_rbo, "Failed to generate renderbuffer id."); - GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo) ); - GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, depthComponent, _width, _height) ); - GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) ); - - GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER - , GL_DEPTH_ATTACHMENT - , GL_RENDERBUFFER - , m_rbo - ) ); - } - else - { - GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER - , GL_DEPTH_ATTACHMENT - , m_depth.m_target - , m_depth.m_id - , 0 - ) ); - } - } - - BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) - , "glCheckFramebufferStatus failed 0x%08x" - , glCheckFramebufferStatus(GL_FRAMEBUFFER) - ); - - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); - } - - void RenderTarget::destroy() - { - GL_CHECK(glDeleteFramebuffers(1, &m_fbo) ); - - if (0 != m_rbo) - { - GL_CHECK(glDeleteRenderbuffers(1, &m_rbo) ); - } - - m_color.destroy(); - m_depth.destroy(); - } - - void ConstantBuffer::commit() - { - reset(); - - do - { - uint32_t opcode = read(); - - if (ConstantType::End == opcode) - { - break; - } - - ConstantType::Enum type; - uint16_t loc; - uint16_t num; - uint16_t copy; - decodeOpcode(opcode, type, loc, num, copy); - - const char* data; - if (copy) - { - data = read(g_constantTypeSize[type]*num); - } - else - { - memcpy(&data, read(sizeof(void*) ), sizeof(void*) ); - } - -#define CASE_IMPLEMENT_UNIFORM(_uniform, _glsuffix, _dxsuffix, _type) \ - case ConstantType::_uniform: \ - { \ - _type* value = (_type*)data; \ - GL_CHECK(glUniform##_glsuffix(loc, num, value) ); \ - } \ - break; - -#define CASE_IMPLEMENT_UNIFORM_T(_uniform, _glsuffix, _dxsuffix, _type) \ - case ConstantType::_uniform: \ - { \ - _type* value = (_type*)data; \ - GL_CHECK(glUniform##_glsuffix(loc, num, GL_FALSE, value) ); \ - } \ - break; - - switch (type) - { -// case ConstantType::Uniform1iv: -// { -// int* value = (int*)data; -// BX_TRACE("Uniform1iv sampler %d, loc %d (num %d, copy %d)", *value, loc, num, copy); -// GL_CHECK(glUniform1iv(loc, num, value) ); -// } -// break; -// - - CASE_IMPLEMENT_UNIFORM(Uniform1i, 1iv, I, int); - CASE_IMPLEMENT_UNIFORM(Uniform1f, 1fv, F, float); - CASE_IMPLEMENT_UNIFORM(Uniform1iv, 1iv, I, int); - CASE_IMPLEMENT_UNIFORM(Uniform1fv, 1fv, F, float); - CASE_IMPLEMENT_UNIFORM(Uniform2fv, 2fv, F, float); - CASE_IMPLEMENT_UNIFORM(Uniform3fv, 3fv, F, float); - CASE_IMPLEMENT_UNIFORM(Uniform4fv, 4fv, F, float); - CASE_IMPLEMENT_UNIFORM_T(Uniform3x3fv, Matrix3fv, F, float); - CASE_IMPLEMENT_UNIFORM_T(Uniform4x4fv, Matrix4fv, F, float); - - case ConstantType::End: - break; - - default: - BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", m_pos, opcode, type, loc, num, copy); - break; - } - -#undef CASE_IMPLEMENT_UNIFORM -#undef CASE_IMPLEMENT_UNIFORM_T - - } while (true); - } - - void TextVideoMemBlitter::setup() - { - uint32_t width = s_renderCtx.m_resolution.m_width; - uint32_t height = s_renderCtx.m_resolution.m_height; - - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); - GL_CHECK(glViewport(0, 0, width, height) ); - - GL_CHECK(glDisable(GL_DEPTH_TEST) ); - GL_CHECK(glDepthFunc(GL_ALWAYS) ); - GL_CHECK(glDisable(GL_CULL_FACE) ); - GL_CHECK(glDisable(GL_BLEND) ); - GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) ); -#if BGFX_CONFIG_RENDERER_OPENGL - GL_CHECK(glDisable(GL_ALPHA_TEST) ); -#endif // BGFX_CONFIG_RENDERER_OPENGL - - Material& material = s_renderCtx.m_materials[m_material.idx]; - GL_CHECK(glUseProgram(material.m_id) ); - GL_CHECK(glUniform1i(material.m_sampler[0], 0) ); - - float proj[16]; - matrix_ortho(proj, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 1000.0f); - - GL_CHECK(glUniformMatrix4fv(material.m_predefined[0].m_loc - , 1 - , GL_FALSE - , proj - ) ); - - GL_CHECK(glActiveTexture(GL_TEXTURE0) ); - GL_CHECK(glBindTexture(GL_TEXTURE_2D, s_renderCtx.m_textures[m_texture.idx].m_id) ); - } - - void TextVideoMemBlitter::render(uint32_t _numIndices) - { - uint32_t numVertices = _numIndices*4/6; - s_renderCtx.m_indexBuffers[m_ib->handle.idx].update(0, _numIndices*2, m_ib->data); - s_renderCtx.m_vertexBuffers[m_vb->handle.idx].update(0, numVertices*m_decl.m_stride, m_vb->data); - - VertexBuffer& vb = s_renderCtx.m_vertexBuffers[m_vb->handle.idx]; - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); - - IndexBuffer& ib = s_renderCtx.m_indexBuffers[m_ib->handle.idx]; - GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) ); - - Material& material = s_renderCtx.m_materials[m_material.idx]; - material.bindAttributes(m_decl, 0); - - GL_CHECK(glDrawElements(GL_TRIANGLES - , _numIndices - , GL_UNSIGNED_SHORT - , (void*)0 - ) ); - } - - void Context::flip() - { - s_renderCtx.flip(); - } - - GLint glGet(GLenum _pname) - { - GLint result; - GL_CHECK(glGetIntegerv(_pname, &result) ); - return result; - } - - void Context::rendererInit() - { - s_renderCtx.init(); - -#if BGFX_CONFIG_DEBUG - GLint numCmpFormats; - GL_CHECK(glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCmpFormats) ); - - BX_TRACE("GL_NUM_COMPRESSED_TEXTURE_FORMATS %d", numCmpFormats); - - GLint* formats = (GLint*)alloca(sizeof(GLint)*numCmpFormats); - glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); - - for (GLint ii = 0; ii < numCmpFormats; ++ii) - { - BX_TRACE("\t%3d: %8x", ii, formats[ii]); - } - -# define GL_GET(_pname, _min) BX_TRACE(#_pname " %d (min: %d)", glGet(_pname), _min) - - GL_GET(GL_MAX_FRAGMENT_UNIFORM_VECTORS, 16); - GL_GET(GL_MAX_VERTEX_UNIFORM_VECTORS, 128); - GL_GET(GL_MAX_VARYING_VECTORS, 8); - GL_GET(GL_MAX_VERTEX_ATTRIBS, 8); - GL_GET(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 8); - GL_GET(GL_MAX_CUBE_MAP_TEXTURE_SIZE, 16); - GL_GET(GL_MAX_TEXTURE_IMAGE_UNITS, 8); - GL_GET(GL_MAX_TEXTURE_SIZE, 64); - GL_GET(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, 0); - GL_GET(GL_MAX_RENDERBUFFER_SIZE, 1); -#endif // BGFX_CONFIG_DEBUG - - const char* extensions = (const char*)glGetString(GL_EXTENSIONS); - - char name[1024]; - const char* pos = extensions; - const char* end = extensions + strlen(extensions); - while (pos < end) - { - uint32_t len; - const char* space = strchr(pos, ' '); - if (NULL != space) - { - len = uint32_min(sizeof(name), (uint32_t)(space - pos) ); - } - else - { - len = uint32_min(sizeof(name), (uint32_t)strlen(pos) ); - } - - strncpy(name, pos, len); - name[len] = '\0'; - - bool supported = false; - for (uint32_t ii = 0; ii < Extension::Count; ++ii) - { - Extension& extension = s_extension[ii]; - if (!extension.m_supported - && extension.m_initialize) - { - if (0 == strcmp(name, extension.m_name) ) - { - extension.m_supported = true; - supported = true; - break; - } - } - } - - BX_TRACE("GL_EXTENSION%s: %s", supported ? " (supported)" : "", name); - BX_UNUSED(supported); - - pos += len+1; - } - - BX_TRACE("Supported extensions:"); - for (uint32_t ii = 0; ii < Extension::Count; ++ii) - { - if (s_extension[ii].m_supported) - { - BX_TRACE("\t%2d: %s", ii, s_extension[ii].m_name); - } - } - - s_renderCtx.m_dxtSupport = true - && s_extension[Extension::EXT_texture_compression_dxt1].m_supported - && s_extension[Extension::CHROMIUM_texture_compression_dxt3].m_supported - && s_extension[Extension::CHROMIUM_texture_compression_dxt5].m_supported - ; - - s_renderCtx.m_dxtSupport |= - s_extension[Extension::EXT_texture_compression_s3tc].m_supported - ; - } - - void Context::rendererShutdown() - { - s_renderCtx.shutdown(); - } - - void Context::rendererCreateIndexBuffer(IndexBufferHandle _handle, Memory* _mem) - { - s_renderCtx.m_indexBuffers[_handle.idx].create(_mem->size, _mem->data); - } - - void Context::rendererDestroyIndexBuffer(IndexBufferHandle _handle) - { - s_renderCtx.m_indexBuffers[_handle.idx].destroy(); - } - - void Context::rendererCreateVertexDecl(VertexDeclHandle _handle, const VertexDecl& _decl) - { - VertexDecl& decl = s_renderCtx.m_vertexDecls[_handle.idx]; - memcpy(&decl, &_decl, sizeof(VertexDecl) ); - dump(decl); - } - - void Context::rendererDestroyVertexDecl(VertexDeclHandle /*_handle*/) - { - } - - void Context::rendererCreateVertexBuffer(VertexBufferHandle _handle, Memory* _mem, VertexDeclHandle _declHandle) - { - s_renderCtx.m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _declHandle); - } - - void Context::rendererDestroyVertexBuffer(VertexBufferHandle _handle) - { - s_renderCtx.m_vertexBuffers[_handle.idx].destroy(); - } - - void Context::rendererCreateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size) - { - s_renderCtx.m_indexBuffers[_handle.idx].create(_size, NULL); - } - - void Context::rendererUpdateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _offset, uint32_t _size, Memory* _mem) - { - s_renderCtx.m_indexBuffers[_handle.idx].update(_offset, uint32_min(_size, _mem->size), _mem->data); - } - - void Context::rendererDestroyDynamicIndexBuffer(IndexBufferHandle _handle) - { - s_renderCtx.m_indexBuffers[_handle.idx].destroy(); - } - - void Context::rendererCreateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size) - { - VertexDeclHandle decl = BGFX_INVALID_HANDLE; - s_renderCtx.m_vertexBuffers[_handle.idx].create(_size, NULL, decl); - } - - void Context::rendererUpdateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, Memory* _mem) - { - s_renderCtx.m_vertexBuffers[_handle.idx].update(_offset, uint32_min(_size, _mem->size), _mem->data); - } - - void Context::rendererDestroyDynamicVertexBuffer(VertexBufferHandle _handle) - { - s_renderCtx.m_vertexBuffers[_handle.idx].destroy(); - } - - void Context::rendererCreateVertexShader(VertexShaderHandle _handle, Memory* _mem) - { - s_renderCtx.m_vertexShaders[_handle.idx].create(GL_VERTEX_SHADER, _mem->data); - } - - void Context::rendererDestroyVertexShader(VertexShaderHandle _handle) - { - s_renderCtx.m_vertexShaders[_handle.idx].destroy(); - } - - void Context::rendererCreateFragmentShader(FragmentShaderHandle _handle, Memory* _mem) - { - s_renderCtx.m_fragmentShaders[_handle.idx].create(GL_FRAGMENT_SHADER, _mem->data); - } - - void Context::rendererDestroyFragmentShader(FragmentShaderHandle _handle) - { - s_renderCtx.m_fragmentShaders[_handle.idx].destroy(); - } - - void Context::rendererCreateMaterial(MaterialHandle _handle, VertexShaderHandle _vsh, FragmentShaderHandle _fsh) - { - s_renderCtx.m_materials[_handle.idx].create(s_renderCtx.m_vertexShaders[_vsh.idx], s_renderCtx.m_fragmentShaders[_fsh.idx]); - } - - void Context::rendererDestroyMaterial(FragmentShaderHandle _handle) - { - s_renderCtx.m_materials[_handle.idx].destroy(); - } - - void Context::rendererCreateTexture(TextureHandle _handle, Memory* _mem, uint32_t _flags) - { - s_renderCtx.m_textures[_handle.idx].create(_mem, _flags); - } - - void Context::rendererDestroyTexture(TextureHandle _handle) - { - s_renderCtx.m_textures[_handle.idx].destroy(); - } - - void Context::rendererCreateRenderTarget(RenderTargetHandle _handle, uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) - { - s_renderCtx.m_renderTargets[_handle.idx].create(_width, _height, _flags, _textureFlags); - } - - void Context::rendererDestroyRenderTarget(RenderTargetHandle _handle) - { - s_renderCtx.m_renderTargets[_handle.idx].destroy(); - } - - void Context::rendererCreateUniform(UniformHandle _handle, ConstantType::Enum _type, uint16_t _num, const char* _name) - { - uint32_t size = g_constantTypeSize[_type]*_num; - void* data = g_realloc(NULL, size); - s_renderCtx.m_uniforms[_handle.idx] = data; - s_renderCtx.m_uniformReg.reg(_name, s_renderCtx.m_uniforms[_handle.idx]); - } - - void Context::rendererDestroyUniform(UniformHandle _handle) - { - g_free(s_renderCtx.m_uniforms[_handle.idx]); - } - - void Context::rendererSaveScreenShot(Memory* _mem) - { - s_renderCtx.saveScreenShot(_mem); - } - - void Context::rendererUpdateUniform(uint16_t _loc, const void* _data, uint32_t _size) - { - memcpy(s_renderCtx.m_uniforms[_loc], _data, _size); - } - - void Context::rendererSubmit() - { - s_renderCtx.updateResolution(m_render->m_resolution); - - int64_t elapsed = -bx::getHPCounter(); -#if BGFX_CONFIG_RENDERER_OPENGL - if (m_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) - { - s_renderCtx.m_queries.begin(0, GL_TIME_ELAPSED); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - - if (0 < m_render->m_iboffset) - { - TransientIndexBuffer* ib = m_render->m_transientIb; - s_renderCtx.m_indexBuffers[ib->handle.idx].update(0, m_render->m_iboffset, ib->data); - } - - if (0 < m_render->m_vboffset) - { - TransientVertexBuffer* vb = m_render->m_transientVb; - s_renderCtx.m_vertexBuffers[vb->handle.idx].update(0, m_render->m_vboffset, vb->data); - } - - m_render->sort(); - - RenderState currentState; - currentState.reset(); - currentState.m_flags = BGFX_STATE_NONE; - - Matrix4 viewProj[BGFX_CONFIG_MAX_VIEWS]; - for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) - { - matrix_mul(viewProj[ii].val, m_render->m_view[ii].val, m_render->m_proj[ii].val); - } - - uint16_t materialIdx = bgfx::invalidHandle; - SortKey key; - uint8_t view = 0xff; - RenderTargetHandle rt = BGFX_INVALID_HANDLE; - int32_t height = m_render->m_resolution.m_height; - float alphaRef = 0.0f; - GLenum primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : GL_TRIANGLES; - uint32_t primNumVerts = 3; - uint32_t baseVertex = 0; - - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); - - uint32_t statsNumPrimsSubmitted = 0; - uint32_t statsNumIndices = 0; - uint32_t statsNumInstances = 0; - uint32_t statsNumPrimsRendered = 0; - - if (0 == (m_render->m_debug&BGFX_DEBUG_IFH) ) - { - for (uint32_t item = 0, numItems = m_render->m_num; item < numItems; ++item) - { - key.decode(m_render->m_sortKeys[item]); - const RenderState& state = m_render->m_renderState[m_render->m_sortValues[item] ]; - - const uint64_t newFlags = state.m_flags; - uint64_t changedFlags = currentState.m_flags ^ state.m_flags; - currentState.m_flags = newFlags; - - if (key.m_view != view) - { - currentState.clear(); - changedFlags = BGFX_STATE_MASK; - currentState.m_flags = newFlags; - - GREMEDY_SETMARKER("view"); - - view = key.m_view; - materialIdx = bgfx::invalidHandle; - - if (m_render->m_rt[view].idx != rt.idx) - { - rt = m_render->m_rt[view]; - - if (rt.idx == bgfx::invalidHandle) - { - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); - height = m_render->m_resolution.m_height; - } - else - { - RenderTarget& renderTarget = s_renderCtx.m_renderTargets[rt.idx]; - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.m_fbo) ); - height = renderTarget.m_height; - } - } - - Rect& rect = m_render->m_rect[view]; - - GL_CHECK(glViewport(rect.m_x, height-rect.m_height-rect.m_y, rect.m_width, rect.m_height) ); - - Clear& clear = m_render->m_clear[view]; - - if (BGFX_CLEAR_NONE != clear.m_flags) - { - GLuint flags = 0; - if (BGFX_CLEAR_COLOR_BIT & clear.m_flags) - { - flags |= GL_COLOR_BUFFER_BIT; - uint32_t rgba = clear.m_rgba; - float rr = (rgba>>24)/255.0f; - float gg = ( (rgba>>16)&0xff)/255.0f; - float bb = ( (rgba>>8)&0xff)/255.0f; - float aa = (rgba&0xff)/255.0f; - GL_CHECK(glClearColor(rr, gg, bb, aa) ); - GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) ); - } - - if (BGFX_CLEAR_DEPTH_BIT & clear.m_flags) - { - flags |= GL_DEPTH_BUFFER_BIT; - GL_CHECK(glClearDepthf(clear.m_depth) ); - GL_CHECK(glDepthMask(GL_TRUE) ); - } - - if (BGFX_CLEAR_STENCIL_BIT & clear.m_flags) - { - flags |= GL_STENCIL_BUFFER_BIT; - GL_CHECK(glClearStencil(clear.m_stencil) ); - } - - if (0 != flags) - { - GL_CHECK(glEnable(GL_SCISSOR_TEST) ); - GL_CHECK(glScissor(rect.m_x, height-rect.m_height-rect.m_y, rect.m_width, rect.m_height) ); - GL_CHECK(glClear(flags) ); - GL_CHECK(glDisable(GL_SCISSOR_TEST) ); - } - } - - GL_CHECK(glEnable(GL_DEPTH_TEST) ); - GL_CHECK(glDepthFunc(GL_LESS) ); - GL_CHECK(glEnable(GL_CULL_FACE) ); - GL_CHECK(glDisable(GL_BLEND) ); - } - - if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK - |BGFX_STATE_ALPHA_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE - |BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK - |BGFX_STATE_POINT_SIZE_MASK) & changedFlags) - { - if (BGFX_STATE_CULL_MASK & changedFlags) - { - if (BGFX_STATE_CULL_CW & newFlags) - { - GL_CHECK(glEnable(GL_CULL_FACE) ); - GL_CHECK(glCullFace(GL_BACK) ); - } - else if (BGFX_STATE_CULL_CCW & newFlags) - { - GL_CHECK(glEnable(GL_CULL_FACE) ); - GL_CHECK(glCullFace(GL_FRONT) ); - } - else - { - GL_CHECK(glDisable(GL_CULL_FACE) ); - } - } - - if (BGFX_STATE_DEPTH_WRITE & changedFlags) - { - GL_CHECK(glDepthMask(!!(BGFX_STATE_DEPTH_WRITE & newFlags) ) ); - } - - if (BGFX_STATE_DEPTH_TEST_MASK & changedFlags) - { - uint32_t func = (newFlags&BGFX_STATE_DEPTH_TEST_MASK)>>BGFX_STATE_DEPTH_TEST_SHIFT; - - if (0 != func) - { - GL_CHECK(glEnable(GL_DEPTH_TEST) ); - GL_CHECK(glDepthFunc(s_depthFunc[func]) ); - } - else - { - GL_CHECK(glDisable(GL_DEPTH_TEST) ); - } - } - - if ( (BGFX_STATE_ALPHA_TEST|BGFX_STATE_ALPHA_REF_MASK) & changedFlags) - { - uint32_t ref = (newFlags&BGFX_STATE_ALPHA_REF_MASK)>>BGFX_STATE_ALPHA_REF_SHIFT; - alphaRef = ref/255.0f; - -#if BGFX_CONFIG_RENDERER_OPENGL - if (BGFX_STATE_ALPHA_TEST & newFlags) - { - GL_CHECK(glEnable(GL_ALPHA_TEST) ); - } - else - { - GL_CHECK(glDisable(GL_ALPHA_TEST) ); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - } - -#if BGFX_CONFIG_RENDERER_OPENGL - if ( (BGFX_STATE_PT_POINTS|BGFX_STATE_POINT_SIZE_MASK) & changedFlags) - { - float pointSize = (float)(uint32_max(1, (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) ); - GL_CHECK(glPointSize(pointSize) ); - } -#endif // BGFX_CONFIG_RENDERER_OPENGL - - if ( (BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags) - { - GLboolean alpha = !!(newFlags&BGFX_STATE_ALPHA_WRITE); - GLboolean rgb = !!(newFlags&BGFX_STATE_RGB_WRITE); - GL_CHECK(glColorMask(rgb, rgb, rgb, alpha) ); - } - - if (BGFX_STATE_BLEND_MASK & changedFlags) - { - if (BGFX_STATE_BLEND_MASK & newFlags) - { - uint32_t blend = (newFlags&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT; - uint32_t src = blend&0xf; - uint32_t dst = (blend>>4)&0xf; - GL_CHECK(glEnable(GL_BLEND) ); - GL_CHECK(glBlendFunc(s_blendFactor[src], s_blendFactor[dst]) ); - } - else - { - GL_CHECK(glDisable(GL_BLEND) ); - } - } - - uint8_t primIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT); - primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : s_primType[primIndex]; - primNumVerts = s_primNumVerts[primIndex]; - } - - bool materialChanged = false; - bool constantsChanged = state.m_constBegin < state.m_constEnd; - bool bindAttribs = false; - rendererUpdateUniforms(m_render->m_constantBuffer, state.m_constBegin, state.m_constEnd); - - if (key.m_material != materialIdx) - { - materialIdx = key.m_material; - GLuint id = bgfx::invalidHandle == materialIdx ? 0 : s_renderCtx.m_materials[materialIdx].m_id; - GL_CHECK(glUseProgram(id) ); - materialChanged = - constantsChanged = - bindAttribs = true; - } - - if (bgfx::invalidHandle != materialIdx) - { - Material& material = s_renderCtx.m_materials[materialIdx]; - - if (constantsChanged) - { - material.m_constantBuffer->commit(); - } - - for (uint32_t ii = 0, num = material.m_numPredefined; ii < num; ++ii) - { - PredefinedUniform& predefined = material.m_predefined[ii]; - switch (predefined.m_type) - { - case PredefinedUniform::ViewRect: - { - float rect[4]; - rect[0] = m_render->m_rect[view].m_x; - rect[1] = m_render->m_rect[view].m_y; - rect[2] = m_render->m_rect[view].m_width; - rect[3] = m_render->m_rect[view].m_height; - - GL_CHECK(glUniform4fv(predefined.m_loc - , 1 - , &rect[0] - ) ); - } - break; - - case PredefinedUniform::ViewTexel: - { - float rect[4]; - rect[0] = 1.0f/float(m_render->m_rect[view].m_width); - rect[1] = 1.0f/float(m_render->m_rect[view].m_height); - - GL_CHECK(glUniform4fv(predefined.m_loc - , 1 - , &rect[0] - ) ); - } - break; - - case PredefinedUniform::View: - { - GL_CHECK(glUniformMatrix4fv(predefined.m_loc - , 1 - , GL_FALSE - , m_render->m_view[view].val - ) ); - } - break; - - case PredefinedUniform::ViewProj: - { - GL_CHECK(glUniformMatrix4fv(predefined.m_loc - , 1 - , GL_FALSE - , viewProj[view].val - ) ); - } - break; - - case PredefinedUniform::Model: - { - const Matrix4& model = m_render->m_matrixCache.m_cache[state.m_matrix]; - GL_CHECK(glUniformMatrix4fv(predefined.m_loc - , uint32_min(predefined.m_count, state.m_num) - , GL_FALSE - , model.val - ) ); - } - break; - - case PredefinedUniform::ModelViewProj: - { - Matrix4 modelViewProj; - const Matrix4& model = m_render->m_matrixCache.m_cache[state.m_matrix]; - matrix_mul(modelViewProj.val, model.val, viewProj[view].val); - - GL_CHECK(glUniformMatrix4fv(predefined.m_loc - , 1 - , GL_FALSE - , modelViewProj.val - ) ); - } - break; - - case PredefinedUniform::ModelViewProjX: - { - const Matrix4& model = m_render->m_matrixCache.m_cache[state.m_matrix]; - - static const BX_ALIGN_STRUCT_16(float) s_bias[16] = - { - 0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.5f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, - }; - - uint8_t other = m_render->m_other[view]; - Matrix4 viewProjBias; - matrix_mul(viewProjBias.val, viewProj[other].val, s_bias); - - Matrix4 modelViewProj; - matrix_mul(modelViewProj.val, model.val, viewProjBias.val); - - GL_CHECK(glUniformMatrix4fv(predefined.m_loc - , 1 - , GL_FALSE - , modelViewProj.val - ) ); - } - break; - - case PredefinedUniform::ViewProjX: - { - static const BX_ALIGN_STRUCT_16(float) s_bias[16] = - { - 0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.5f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, - }; - - uint8_t other = m_render->m_other[view]; - Matrix4 viewProjBias; - matrix_mul(viewProjBias.val, viewProj[other].val, s_bias); - - GL_CHECK(glUniformMatrix4fv(predefined.m_loc - , 1 - , GL_FALSE - , viewProjBias.val - ) ); - } - break; - - case PredefinedUniform::AlphaRef: - { - GL_CHECK(glUniform1f(predefined.m_loc, alphaRef) ); - } - break; - - case PredefinedUniform::Count: - break; - } - } - -// if (BGFX_STATE_TEX_MASK & changedFlags) - { - uint64_t flag = BGFX_STATE_TEX0; - for (uint32_t stage = 0; stage < BGFX_STATE_TEX_COUNT; ++stage) - { - const Sampler& sampler = state.m_sampler[stage]; - Sampler& current = currentState.m_sampler[stage]; - if (current.m_idx != sampler.m_idx - || current.m_flags != sampler.m_flags - || materialChanged) - { - GL_CHECK(glActiveTexture(GL_TEXTURE0+stage) ); - if (bgfx::invalidHandle != sampler.m_idx) - { - switch (sampler.m_flags&BGFX_SAMPLER_TYPE_MASK) - { - case BGFX_SAMPLER_TEXTURE: - { - const Texture& texture = s_renderCtx.m_textures[sampler.m_idx]; - GL_CHECK(glBindTexture(texture.m_target, texture.m_id) ); - } - break; - - case BGFX_SAMPLER_RENDERTARGET_COLOR: - { - const RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; - GL_CHECK(glBindTexture(rt.m_color.m_target, rt.m_color.m_id) ); - } - break; - - case BGFX_SAMPLER_RENDERTARGET_DEPTH: - { - const RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; - GL_CHECK(glBindTexture(rt.m_depth.m_target, rt.m_depth.m_id) ); - } - break; - } - } - } - - current = sampler; - flag <<= 1; - } - - GL_CHECK(glActiveTexture(GL_TEXTURE0) ); - } - - if (currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx || materialChanged) - { - currentState.m_vertexBuffer = state.m_vertexBuffer; - - uint16_t handle = state.m_vertexBuffer.idx; - if (bgfx::invalidHandle != handle) - { - VertexBuffer& vb = s_renderCtx.m_vertexBuffers[handle]; - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); - bindAttribs = true; - } - else - { - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); - } - } - - if (currentState.m_indexBuffer.idx != state.m_indexBuffer.idx) - { - currentState.m_indexBuffer = state.m_indexBuffer; - - uint16_t handle = state.m_indexBuffer.idx; - if (bgfx::invalidHandle != handle) - { - IndexBuffer& ib = s_renderCtx.m_indexBuffers[handle]; - GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) ); - } - else - { - GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); - } - } - - if (bgfx::invalidHandle != currentState.m_vertexBuffer.idx) - { - if (baseVertex != state.m_startVertex - || bindAttribs) - { - baseVertex = state.m_startVertex; - VertexBuffer& vb = s_renderCtx.m_vertexBuffers[state.m_vertexBuffer.idx]; - uint16_t decl = vb.m_decl.idx == bgfx::invalidHandle ? state.m_vertexDecl.idx : vb.m_decl.idx; - const Material& material = s_renderCtx.m_materials[materialIdx]; - material.bindAttributes(s_renderCtx.m_vertexDecls[decl], state.m_startVertex); - - if (invalidHandle != state.m_instanceDataBuffer.idx) - { - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, s_renderCtx.m_vertexBuffers[state.m_instanceDataBuffer.idx].m_id) ); - material.bindInstanceData(state.m_instanceDataStride, state.m_instanceDataOffset); - } - } - - uint32_t numIndices = 0; - uint32_t numPrimsSubmitted = 0; - uint32_t numInstances = 0; - uint32_t numPrimsRendered = 0; - - if (bgfx::invalidHandle != state.m_indexBuffer.idx) - { - if (BGFX_DRAW_WHOLE_INDEX_BUFFER == state.m_startIndex) - { - numIndices = s_renderCtx.m_indexBuffers[state.m_indexBuffer.idx].m_size/2; - numPrimsSubmitted = numIndices/primNumVerts; - numInstances = state.m_numInstances; - numPrimsRendered = numPrimsSubmitted*state.m_numInstances; - - GL_CHECK(s_drawElementsInstanced(primType - , s_renderCtx.m_indexBuffers[state.m_indexBuffer.idx].m_size/2 - , GL_UNSIGNED_SHORT - , (void*)0 - , state.m_numInstances - ) ); - } - else if (primNumVerts <= state.m_numIndices) - { - numIndices = state.m_numIndices; - numPrimsSubmitted = numIndices/primNumVerts; - numInstances = state.m_numInstances; - numPrimsRendered = numPrimsSubmitted*state.m_numInstances; - - GL_CHECK(s_drawElementsInstanced(primType - , numIndices - , GL_UNSIGNED_SHORT - , (void*)(uintptr_t)(state.m_startIndex*2) - , state.m_numInstances - ) ); - } - } - else - { - numPrimsSubmitted = state.m_numVertices/primNumVerts; - numInstances = state.m_numInstances; - numPrimsRendered = numPrimsSubmitted*state.m_numInstances; - - GL_CHECK(s_drawArraysInstanced(primType - , 0 - , state.m_numVertices - , state.m_numInstances - ) ); - } - - statsNumPrimsSubmitted += numPrimsSubmitted; - statsNumIndices += numIndices; - statsNumInstances += numInstances; - statsNumPrimsRendered += numPrimsRendered; - } - } - } - } - - int64_t now = bx::getHPCounter(); - elapsed += now; - - static int64_t last = now; - int64_t frameTime = now - last; - last = now; - - if (m_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) - { - double elapsedGpuMs = 0.0; -#if BGFX_CONFIG_RENDERER_OPENGL - s_renderCtx.m_queries.end(GL_TIME_ELAPSED); - uint64_t elapsedGl = s_renderCtx.m_queries.getResult(0); - elapsedGpuMs = double(elapsedGl)/1e6; -#endif // BGFX_CONFIG_RENDERER_OPENGL - - TextVideoMem& tvm = s_renderCtx.m_textVideoMem; - - static int64_t next = now; - - if (now >= next) - { - next = now + bx::getHPFrequency(); - double freq = double(bx::getHPFrequency() ); - double toMs = 1000.0/freq; - double elapsedCpuMs = double(elapsed)*toMs; - - tvm.clear(); - uint16_t pos = 10; - tvm.printf(10, pos++, 0x8e, " Frame CPU: %3.4f [ms] / %3.2f", double(frameTime)*toMs, freq/frameTime); - tvm.printf(10, pos++, 0x8e, " Draw calls: %4d / CPU %3.4f [ms] %c GPU %3.4f [ms]" - , m_render->m_num - , elapsedCpuMs - , elapsedCpuMs > elapsedGpuMs ? '>' : '<' - , elapsedGpuMs - ); - tvm.printf(10, pos++, 0x8e, " Prims: %7d (#inst: %5d), submitted: %7d" - , statsNumPrimsRendered - , statsNumInstances - , statsNumPrimsSubmitted - ); - tvm.printf(10, pos++, 0x8e, " Indices: %7d", statsNumIndices); - tvm.printf(10, pos++, 0x8e, " DVB size: %7d", m_render->m_vboffset); - tvm.printf(10, pos++, 0x8e, " DIB size: %7d", m_render->m_iboffset); - - uint8_t attr[2] = { 0x89, 0x8a }; - uint8_t attrIndex = m_render->m_waitSubmit < m_render->m_waitRender; - - tvm.printf(10, pos++, attr[attrIndex&1], "Submit wait: %3.4f [ms]", double(m_render->m_waitSubmit)*toMs); - tvm.printf(10, pos++, attr[(attrIndex+1)&1], "Render wait: %3.4f [ms]", double(m_render->m_waitRender)*toMs); - } - - m_textVideoMemBlitter.blit(tvm); - } - else if (m_render->m_debug & BGFX_DEBUG_TEXT) - { - m_textVideoMemBlitter.blit(m_render->m_textVideoMem); - } - - GREMEDY_FRAMETERMINATOR(); - } -} - -#endif // (BGFX_CONFIG_RENDERER_OPENGLES|BGFX_CONFIG_RENDERER_OPENGL) + static PFNGLVERTEXATTRIBDIVISORBGFXPROC s_vertexAttribDivisor = stubVertexAttribDivisor; + static PFNGLDRAWARRAYSINSTANCEDBGFXPROC s_drawArraysInstanced = stubDrawArraysInstanced; + static PFNGLDRAWELEMENTSINSTANCEDBGFXPROC s_drawElementsInstanced = stubDrawElementsInstanced; + + typedef void (*PostSwapBuffersFn)(uint32_t _width, uint32_t _height); + +#if BX_PLATFORM_NACL + void naclSwapCompleteCb(void* _data, int32_t _result); + + PP_CompletionCallback naclSwapComplete = + { + naclSwapCompleteCb, + NULL, + PP_COMPLETIONCALLBACK_FLAG_NONE + }; +#endif // BX_PLATFORM_NACL + + struct RendererContext + { + RendererContext() + : m_dxtSupport(false) + , m_flip(false) + , m_postSwapBuffers(NULL) + , m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT) +#if BX_PLATFORM_NACL + , m_context(0) + , m_instance(0) + , m_instInterface(NULL) + , m_graphicsInterface(NULL) +#elif BGFX_USE_WGL + , m_context(NULL) + , m_hdc(NULL) +#elif BGFX_USE_EGL + , m_context(NULL) + , m_display(NULL) + , m_surface(NULL) +#elif BX_PLATFORM_LINUX + , m_context(0) + , m_window(0) + , m_display(NULL) +#endif // BX_PLATFORM_ + { + memset(&m_resolution, 0, sizeof(m_resolution) ); + } + + void updateResolution(const Resolution& _resolution) + { + if (m_resolution.m_width != _resolution.m_width + || m_resolution.m_height != _resolution.m_height + || m_resolution.m_flags != _resolution.m_flags) + { + m_textVideoMem.resize(false, _resolution.m_width, _resolution.m_height); + m_textVideoMem.clear(); + + m_resolution = _resolution; + setRenderContextSize(_resolution.m_width, _resolution.m_height); + } + } + + void setRenderContextSize(uint32_t _width, uint32_t _height) + { + if (_width != 0 + || _height != 0) + { +#if BX_PLATFORM_NACL + if (0 == m_context) + { + BX_TRACE("create context"); + + int32_t attribs[] = + { + PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, + PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, + PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, + PP_GRAPHICS3DATTRIB_SAMPLES, 0, + PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, + PP_GRAPHICS3DATTRIB_WIDTH, _width, + PP_GRAPHICS3DATTRIB_HEIGHT, _height, + PP_GRAPHICS3DATTRIB_NONE + }; + + m_context = m_graphicsInterface->Create(m_instance, 0, attribs); + m_instInterface->BindGraphics(m_instance, m_context); + glSetCurrentContextPPAPI(m_context); + m_graphicsInterface->SwapBuffers(m_context, naclSwapComplete); + +#if 0 + # define GL_IMPORT(_optional, _proto, _func) \ + { \ + _func = (_proto)eglGetProcAddress(#_func); \ + BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGL context. eglGetProcAddress(\"%s\")", #_func); \ + } + # include "glimports.h" + # undef GL_IMPORT +#endif + } + else + { + m_graphicsInterface->ResizeBuffers(m_context, _width, _height); + } + +#elif BGFX_USE_WGL + if (NULL == m_hdc) + { + m_opengl32dll = LoadLibrary("opengl32.dll"); + BGFX_FATAL(NULL != m_opengl32dll, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to load opengl32.dll."); + + wglGetProcAddress = (PFNWGLGETPROCADDRESSPROC)GetProcAddress(m_opengl32dll, "wglGetProcAddress"); + BGFX_FATAL(NULL != wglGetProcAddress, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglGetProcAddress."); + + wglMakeCurrent = (PFNWGLMAKECURRENTPROC)GetProcAddress(m_opengl32dll, "wglMakeCurrent"); + BGFX_FATAL(NULL != wglMakeCurrent, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglMakeCurrent."); + + wglCreateContext = (PFNWGLCREATECONTEXTPROC)GetProcAddress(m_opengl32dll, "wglCreateContext"); + BGFX_FATAL(NULL != wglCreateContext, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglCreateContext."); + + wglDeleteContext = (PFNWGLDELETECONTEXTPROC)GetProcAddress(m_opengl32dll, "wglDeleteContext"); + BGFX_FATAL(NULL != wglDeleteContext, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed get wglDeleteContext."); + + m_hdc = GetDC(g_bgfxHwnd); + BGFX_FATAL(NULL != m_hdc, bgfx::Fatal::OPENGL_UnableToCreateContext, "GetDC failed!"); + + PIXELFORMATDESCRIPTOR pfd; + memset(&pfd, 0, sizeof(pfd) ); + pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + pfd.cAlphaBits = 8; + pfd.cDepthBits = 24; + pfd.cStencilBits = 8; + pfd.iLayerType = PFD_MAIN_PLANE; + + int pixelFormat = ChoosePixelFormat(m_hdc, &pfd); + BGFX_FATAL(0 != pixelFormat, bgfx::Fatal::OPENGL_UnableToCreateContext, "ChoosePixelFormat failed!"); + + DescribePixelFormat(m_hdc, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + + int result; + result = SetPixelFormat(m_hdc, pixelFormat, &pfd); + BGFX_FATAL(0 != result, bgfx::Fatal::OPENGL_UnableToCreateContext, "SetPixelFormat failed!"); + + m_context = wglCreateContext(m_hdc); + BGFX_FATAL(NULL != m_context, bgfx::Fatal::OPENGL_UnableToCreateContext, "wglCreateContext failed!"); + + result = wglMakeCurrent(m_hdc, m_context); + BGFX_FATAL(0 != result, bgfx::Fatal::OPENGL_UnableToCreateContext, "wglMakeCurrent failed!"); + +# define GL_IMPORT(_optional, _proto, _func) \ + { \ + _func = (_proto)wglGetProcAddress(#_func); \ + if (_func == NULL) \ + { \ + _func = (_proto)GetProcAddress(m_opengl32dll, #_func); \ + } \ + BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGL context. wglGetProcAddress(\"%s\")", #_func); \ + } +# include "glimports.h" +# undef GL_IMPORT + } +#elif BX_PLATFORM_LINUX + + if (0 == m_display) + { + Display* display = XOpenDisplay(0); + XLockDisplay(display); + BGFX_FATAL(display, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to open X display (0)."); + + int glxMajor, glxMinor; + if (!glXQueryVersion(display, &glxMajor, &glxMinor)) + { + BGFX_FATAL(false, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to query GLX version"); + } + BGFX_FATAL((glxMajor == 1 && glxMinor >= 3) || glxMajor > 1, bgfx::Fatal::OPENGL_UnableToCreateContext, "GLX version is not >=1.3 (%d.%d).", glxMajor, glxMinor); + + const int glxAttribs[] = + { + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_RED_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_DOUBLEBUFFER, True, + None, + }; + + // Find suitable config + GLXFBConfig bestconfig = NULL; + + int nconfigs; + GLXFBConfig* configs = glXChooseFBConfig(display, DefaultScreen(display), glxAttribs, &nconfigs); + + XVisualInfo* visualInfo = 0; + for (int ii = 0; ii < nconfigs; ++ii) + { + visualInfo = glXGetVisualFromFBConfig(display, configs[ii]); + if (visualInfo) + { + // Check if meets min spec + bool validconfig = true; + for (uint32_t attridx = 0; attridx < countof(glxAttribs)-1 && glxAttribs[attridx] != None; attridx += 2) + { + int value; + glXGetFBConfigAttrib(display, configs[ii], glxAttribs[attridx], &value); + if (value < glxAttribs[attridx + 1]) + { + validconfig = false; + break; + } + } + + if (validconfig) + { + bestconfig = configs[ii]; + break; + } + } + + XFree(visualInfo); + visualInfo = 0; + } + + XFree(configs); + BGFX_FATAL(visualInfo, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to find a suitable X11 display configuration."); + + // Generate colormaps + XSetWindowAttributes windowAttrs; + windowAttrs.colormap = XCreateColormap(display, RootWindow(display, visualInfo->screen), visualInfo->visual, AllocNone); + windowAttrs.background_pixmap = None; + windowAttrs.border_pixel = 0; + + Window window = XCreateWindow( + display + , RootWindow(display, visualInfo->screen) + , 0, 0 + , _width, _height, 0, visualInfo->depth + , InputOutput + , visualInfo->visual + , CWBorderPixel|CWColormap + , &windowAttrs + ); + BGFX_FATAL(window, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create X11 window."); + + XMapRaised(display, window); + XFlush(display); + XFree(visualInfo); + + BX_TRACE("create context"); + + typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + BGFX_FATAL(glXCreateContextAttribsARB, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to get glXCreateContextAttribsARB."); + + const int contextArrib[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + None, + }; + + m_context = glXCreateContextAttribsARB(display, bestconfig, 0, True, contextArrib); + BGFX_FATAL(m_context, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create GLX context."); + + glXMakeCurrent(display, window, m_context); + +# define GL_IMPORT(_optional, _proto, _func) \ + { \ + _func = (_proto)glXGetProcAddress((const GLubyte*)#_func); \ + BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGL context. glXGetProcAddress %s", #_func); \ + } +# include "glimports.h" +# undef GL_IMPORT + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glXSwapBuffers(display, window); + + m_display = display; + m_window = window; + XUnlockDisplay(display); + } + else + { + XResizeWindow(m_display, m_window, _width, _height); + } +#elif BGFX_USE_EGL + if (NULL == m_context) + { + m_display = eglGetDisplay(NULL); + BGFX_FATAL(m_display != EGL_NO_DISPLAY, Fatal::OPENGL_UnableToCreateContext, "Failed to create display 0x%08x", m_display); + + EGLint major = 0; + EGLint minor = 0; + EGLBoolean success = eglInitialize(m_display, &major, &minor); + BGFX_FATAL(success && major >= 1 && minor >= 4, Fatal::OPENGL_UnableToCreateContext, "Failed to initialize %d.%d", major, minor); + + EGLint attrs[] = + { +# if BX_PLATFORM_ANDROID + EGL_DEPTH_SIZE, 16, +# else + EGL_DEPTH_SIZE, 24, +# endif // BX_PLATFORM_ + + EGL_NONE + }; + EGLint numConfig = 0; + EGLConfig config = 0; + success = eglChooseConfig(m_display, attrs, &config, 1, &numConfig); + BGFX_FATAL(success, Fatal::OPENGL_UnableToCreateContext, "eglChooseConfig"); + + m_surface = eglCreateWindowSurface(m_display, config, (EGLNativeWindowType)g_bgfxHwnd, NULL); + BGFX_FATAL(m_surface != EGL_NO_SURFACE, Fatal::OPENGL_UnableToCreateContext, "Failed to create surface."); + + m_context = eglCreateContext(m_display, config, EGL_NO_CONTEXT, NULL); + BGFX_FATAL(m_context != EGL_NO_CONTEXT, Fatal::OPENGL_UnableToCreateContext, "Failed to create context."); + + success = eglMakeCurrent(m_display, m_surface, m_surface, m_context); + BGFX_FATAL(success, Fatal::OPENGL_UnableToCreateContext, "Failed to set context."); + +# define GL_IMPORT(_optional, _proto, _func) \ + { \ + _func = (_proto)eglGetProcAddress(#_func); \ + BGFX_FATAL(_optional || NULL != _func, bgfx::Fatal::OPENGL_UnableToCreateContext, "Failed to create OpenGLES context. eglGetProcAddress(\"%s\")", #_func); \ + } +# include "glimports.h" +# undef GL_IMPORT + } +#endif // BX_PLATFORM_ + } + + if (NULL != glVertexAttribDivisor + && NULL != glDrawArraysInstanced + && NULL != glDrawElementsInstanced) + { + s_vertexAttribDivisor = glVertexAttribDivisor; + s_drawArraysInstanced = glDrawArraysInstanced; + s_drawElementsInstanced = glDrawElementsInstanced; + } + else + { + s_vertexAttribDivisor = stubVertexAttribDivisor; + s_drawArraysInstanced = stubDrawArraysInstanced; + s_drawElementsInstanced = stubDrawElementsInstanced; + } + + m_flip = true; + } + + void flip() + { + if (m_flip) + { +#if BX_PLATFORM_NACL + glSetCurrentContextPPAPI(m_context); + m_graphicsInterface->SwapBuffers(m_context, naclSwapComplete); +#elif BGFX_USE_WGL + wglMakeCurrent(m_hdc, m_context); + SwapBuffers(m_hdc); +#elif BGFX_USE_EGL + eglMakeCurrent(m_display, m_surface, m_surface, m_context); + eglSwapBuffers(m_display, m_surface); +#elif BX_PLATFORM_LINUX + glXSwapBuffers(m_display, m_window); +#endif // BX_PLATFORM_ + } + + if (NULL != m_postSwapBuffers) + { + m_postSwapBuffers(m_resolution.m_width, m_resolution.m_height); + } + } + + void saveScreenShot(Memory* _mem) + { +#if BGFX_CONFIG_RENDERER_OPENGL + void* data = g_realloc(NULL, m_resolution.m_width*m_resolution.m_height*4); + glReadPixels(0, 0, m_resolution.m_width, m_resolution.m_height, GL_RGBA, GL_UNSIGNED_BYTE, data); + + uint8_t* rgba = (uint8_t*)data; + for (uint32_t ii = 0, num = m_resolution.m_width*m_resolution.m_height; ii < num; ++ii) + { + uint8_t temp = rgba[0]; + rgba[0] = rgba[2]; + rgba[2] = temp; + rgba += 4; + } + + saveTga( (const char*)_mem->data, m_resolution.m_width, m_resolution.m_height, m_resolution.m_width*4, data, false, true); + g_free(data); +#endif // BGFX_CONFIG_RENDERER_OPENGL + } + + void init() + { + setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT); +#if BGFX_CONFIG_RENDERER_OPENGL + m_queries.create(); +#endif // BGFX_CONFIG_RENDERER_OPENGL + } + + void shutdown() + { +#if BGFX_CONFIG_RENDERER_OPENGL + m_queries.destroy(); +#endif // BGFX_CONFIG_RENDERER_OPENGL + +#if BGFX_USE_WGL + if (NULL != m_hdc) + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(m_context); + m_context = NULL; + } + + FreeLibrary(m_opengl32dll); +#elif BGFX_USE_EGL + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(m_display, m_context); + eglDestroySurface(m_display, m_surface); + eglTerminate(m_display); + m_context = NULL; +#endif // BGFX_USE_ + } + + IndexBuffer m_indexBuffers[BGFX_CONFIG_MAX_INDEX_BUFFERS]; + VertexBuffer m_vertexBuffers[BGFX_CONFIG_MAX_VERTEX_BUFFERS]; + Shader m_vertexShaders[BGFX_CONFIG_MAX_VERTEX_SHADERS]; + Shader m_fragmentShaders[BGFX_CONFIG_MAX_FRAGMENT_SHADERS]; + Material m_materials[BGFX_CONFIG_MAX_MATERIALS]; + Texture m_textures[BGFX_CONFIG_MAX_TEXTURES]; + VertexDecl m_vertexDecls[BGFX_CONFIG_MAX_VERTEX_DECLS]; + RenderTarget m_renderTargets[BGFX_CONFIG_MAX_RENDER_TARGETS]; + UniformRegistry m_uniformReg; + void* m_uniforms[BGFX_CONFIG_MAX_UNIFORMS]; +#if BGFX_CONFIG_RENDERER_OPENGL + Queries m_queries; +#endif // BGFX_CONFIG_RENDERER_OPENGL + + TextVideoMem m_textVideoMem; + + Resolution m_resolution; + bool m_dxtSupport; + bool m_flip; + + PostSwapBuffersFn m_postSwapBuffers; + uint64_t m_hash; + +#if BX_PLATFORM_NACL + PP_Resource m_context; + PP_Instance m_instance; + const PPB_Instance* m_instInterface; + const PPB_Graphics3D* m_graphicsInterface; +#elif BGFX_USE_WGL + HMODULE m_opengl32dll; + HGLRC m_context; + HDC m_hdc; +#elif BGFX_USE_EGL + EGLContext m_context; + EGLDisplay m_display; + EGLSurface m_surface; +#elif BX_PLATFORM_LINUX + GLXContext m_context; + Window m_window; + Display* m_display; +#endif // BX_PLATFORM_NACL + }; + + RendererContext s_renderCtx; + +#if BX_PLATFORM_NACL + void naclSetIntefraces(PP_Instance _instance, const PPB_Instance* _instInterface, const PPB_Graphics3D* _graphicsInterface, PostSwapBuffersFn _postSwapBuffers) + { + s_renderCtx.m_instance = _instance; + s_renderCtx.m_instInterface = _instInterface; + s_renderCtx.m_graphicsInterface = _graphicsInterface; + s_renderCtx.m_postSwapBuffers = _postSwapBuffers; + s_renderCtx.setRenderContextSize(BGFX_DEFAULT_WIDTH, BGFX_DEFAULT_HEIGHT); + } + + void naclSwapCompleteCb(void* /*_data*/, int32_t /*_result*/) + { + renderFrame(); + } + +#elif BX_PLATFORM_LINUX + bool linuxGetDisplay(Display** _display, Window* _window) + { + if (!s_renderCtx.m_display) + { + return false; + } + + *_display = s_renderCtx.m_display; + *_window = s_renderCtx.m_window; + return true; + } +#endif // BX_PLATFORM_ + + struct Extension + { + enum Enum + { + EXT_texture_format_BGRA8888, + EXT_texture_compression_s3tc, + EXT_texture_compression_dxt1, + CHROMIUM_texture_compression_dxt3, + CHROMIUM_texture_compression_dxt5, + OES_standard_derivatives, + ARB_get_program_binary, + OES_get_program_binary, + EXT_framebuffer_blit, + ARB_timer_query, + EXT_timer_query, + EXT_texture_sRGB, + ARB_framebuffer_sRGB, + EXT_framebuffer_sRGB, + ARB_multisample, + CHROMIUM_framebuffer_multisample, + ANGLE_translated_shader_source, + ARB_instanced_arrays, + ANGLE_instanced_arrays, + OES_texture_float, + OES_texture_float_linear, + OES_texture_half_float, + OES_texture_half_float_linear, + EXT_occlusion_query_boolean, + + Count + }; + + const char* m_name; + bool m_supported; + bool m_initialize; + }; + + static Extension s_extension[Extension::Count] = + { + // Nvidia BGRA on Linux bug: + // https://groups.google.com/a/chromium.org/forum/?fromgroups#!topic/chromium-reviews/yFfbUdyeUCQ + { "GL_EXT_texture_format_BGRA8888", false, !BX_PLATFORM_LINUX }, + { "GL_EXT_texture_compression_s3tc", false, true }, + { "GL_EXT_texture_compression_dxt1", false, true }, + { "GL_CHROMIUM_texture_compression_dxt3", false, true }, + { "GL_CHROMIUM_texture_compression_dxt5", false, true }, + { "GL_OES_standard_derivatives", false, true }, + { "GL_ARB_get_program_binary", false, true }, + { "GL_OES_get_program_binary", false, false }, + { "GL_EXT_framebuffer_blit", false, true }, + { "GL_ARB_timer_query", false, true }, + { "GL_EXT_timer_query", false, true }, + { "GL_EXT_texture_sRGB", false, true }, + { "GL_ARB_framebuffer_sRGB", false, true }, + { "GL_EXT_framebuffer_sRGB", false, true }, + { "GL_ARB_multisample", false, true }, + { "GL_CHROMIUM_framebuffer_multisample", false, true }, + { "GL_ANGLE_translated_shader_source", false, true }, + { "GL_ARB_instanced_arrays", false, true }, + { "GL_ANGLE_instanced_arrays", false, true }, + { "GL_OES_texture_float", false, true }, + { "GL_OES_texture_float_linear", false, true }, + { "GL_OES_texture_half_float", false, true }, + { "GL_OES_texture_half_float_linear", false, true }, + { "GL_EXT_occlusion_query_boolean", false, true }, + }; + + static const GLenum s_primType[] = + { + GL_TRIANGLES, + GL_LINES, + GL_POINTS, + }; + + static const uint32_t s_primNumVerts[] = + { + 3, + 2, + 1, + }; + + static const char* s_attribName[Attrib::Count] = + { + "a_position", + "a_normal", + "a_color", + "a_color1", + "a_indices", + "a_weight", + "a_texcoord0", + "a_texcoord1", + "a_texcoord2", + "a_texcoord3", + "a_texcoord4", + "a_texcoord5", + "a_texcoord6", + "a_texcoord7", + }; + + static const char* s_instanceDataName[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT] = + { + "i_data0", + "i_data1", + "i_data2", + "i_data3", + "i_data4", + }; + + static const GLenum s_attribType[AttribType::Count] = + { + GL_UNSIGNED_BYTE, + GL_UNSIGNED_SHORT, + GL_FLOAT, + }; + + static const GLenum s_blendFactor[] = + { + 0, // ignored + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA_SATURATE, + }; + + static const GLenum s_depthFunc[] = + { + 0, // ignored + GL_LESS, + GL_LEQUAL, + GL_EQUAL, + GL_GEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_NEVER, + GL_ALWAYS, + }; + + // Specifies the internal format of the texture. + // Must be one of the following symbolic constants: + // GL_ALPHA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA. + static const GLenum s_colorFormat[] = + { + 0, // ignored + GL_RGBA, + GL_RGBA, + }; + + static const GLenum s_depthFormat[] = + { + 0, // ignored + 0, + }; + + static const GLenum s_textureAddress[] = + { + GL_REPEAT, + GL_MIRRORED_REPEAT, + GL_CLAMP_TO_EDGE, + }; + + static const GLenum s_textureFilter[] = + { + GL_LINEAR, + GL_NEAREST, + }; + + struct TextureFormatInfo + { + GLenum m_internalFmt; + GLenum m_format; + GLenum m_type; + uint8_t m_bpp; + }; + + static const TextureFormatInfo s_textureFormat[TextureFormat::Count] = + { + { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_ZERO, GL_ZERO, 1 }, + { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_ZERO, GL_ZERO, 1 }, + { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_ZERO, GL_ZERO, 1 }, + { GL_ZERO, GL_ZERO, GL_ZERO, 0 }, + { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, 1 }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 4 }, +#if BGFX_CONFIG_RENDERER_OPENGL + { GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT, 8 }, +#else + { GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, 8 }, +#endif // BGFX_CONFIG_RENDERER_OPENGL + }; + + const char* glslTypeName(GLuint _type) + { +#define GLSL_TYPE(_ty) case _ty: return #_ty + + switch (_type) + { + GLSL_TYPE(GL_FLOAT); + GLSL_TYPE(GL_FLOAT_VEC2); + GLSL_TYPE(GL_FLOAT_VEC3); + GLSL_TYPE(GL_FLOAT_VEC4); + GLSL_TYPE(GL_FLOAT_MAT2); + GLSL_TYPE(GL_FLOAT_MAT3); + GLSL_TYPE(GL_FLOAT_MAT4); +// GLSL_TYPE(GL_FLOAT_MAT2x3); +// GLSL_TYPE(GL_FLOAT_MAT2x4); +// GLSL_TYPE(GL_FLOAT_MAT3x2); +// GLSL_TYPE(GL_FLOAT_MAT3x4); +// GLSL_TYPE(GL_FLOAT_MAT4x2); +// GLSL_TYPE(GL_FLOAT_MAT4x3); +// GLSL_TYPE(GL_SAMPLER_1D); + GLSL_TYPE(GL_SAMPLER_2D); +// GLSL_TYPE(GL_SAMPLER_3D); + GLSL_TYPE(GL_SAMPLER_CUBE); +// GLSL_TYPE(GL_SAMPLER_1D_SHADOW); +// GLSL_TYPE(GL_SAMPLER_2D_SHADOW); + } + +#undef GLSL_TYPE + + return "UNKNOWN GLSL TYPE!"; + } + + const char* glEnumName(GLenum _enum) + { +#define GLENUM(_ty) case _ty: return #_ty + + switch (_enum) + { + GLENUM(GL_TEXTURE); + GLENUM(GL_RENDERBUFFER); + } + +#undef GLENUM + + return "UNKNOWN GLENUM!"; + } + + ConstantType::Enum convertGlType(GLenum _type) + { + switch (_type) + { + case GL_FLOAT: + return ConstantType::Uniform1fv; + + case GL_FLOAT_VEC2: + return ConstantType::Uniform2fv; + + case GL_FLOAT_VEC3: + return ConstantType::Uniform3fv; + + case GL_FLOAT_VEC4: + return ConstantType::Uniform4fv; + + case GL_FLOAT_MAT2: + break; + + case GL_FLOAT_MAT3: + return ConstantType::Uniform3x3fv; + + case GL_FLOAT_MAT4: + return ConstantType::Uniform4x4fv; + +// case GL_FLOAT_MAT2x3: +// case GL_FLOAT_MAT2x4: +// case GL_FLOAT_MAT3x2: +// case GL_FLOAT_MAT3x4: +// case GL_FLOAT_MAT4x2: +// case GL_FLOAT_MAT4x3: +// break; + + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: +// case GL_SAMPLER_1D: +// case GL_SAMPLER_3D: +// case GL_SAMPLER_1D_SHADOW: +// case GL_SAMPLER_2D_SHADOW: + return ConstantType::Uniform1iv; + }; + + return ConstantType::End; + } + + void Material::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); + + bool cached = false; + +#if BGFX_CONFIG_RENDERER_OPENGL + uint64_t id = (uint64_t(_vsh.m_hash)<<32) | _fsh.m_hash; + id ^= s_renderCtx.m_hash; + + if (s_extension[Extension::ARB_get_program_binary].m_supported) + { + uint32_t length; + g_cache(id, false, NULL, length); + cached = length > 0; + + if (cached) + { + void* data = g_realloc(NULL, length); + g_cache(id, false, data, length); + + StreamRead stream(data, length); + + GLenum format; + stream.read(format); + + GL_CHECK(glProgramBinary(m_id, format, stream.getDataPtr(), stream.remaining() ) ); + + g_free(data); + } + else + { + GL_CHECK(glProgramParameteri(m_id, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE) ); + } + } +#endif // BGFX_CONFIG_RENDERER_OPENGL + + if (!cached) + { + 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; + } + +#if BGFX_CONFIG_RENDERER_OPENGL + if (s_extension[Extension::ARB_get_program_binary].m_supported) + { + GLint programLength; + GLenum format; + GL_CHECK(glGetProgramiv(m_id, GL_PROGRAM_BINARY_LENGTH, &programLength) ); + + uint32_t length = programLength + 4; + uint8_t* data = (uint8_t*)g_realloc(NULL, length); + GL_CHECK(glGetProgramBinary(m_id, programLength, NULL, &format, &data[4]) ); + *(uint32_t*)data = format; + + g_cache(id, true, data, length); + + g_free(data); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL + } + + init(); + } + + void Material::destroy() + { + GL_CHECK(glUseProgram(0) ); + GL_CHECK(glDeleteProgram(m_id) ); + } + + void Material::init() + { + GLint activeAttribs; + GLint activeUniforms; + + GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_ATTRIBUTES, &activeAttribs) ); + GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_UNIFORMS, &activeUniforms) ); + + GLint max0, max1; + GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max0) ); + GL_CHECK(glGetProgramiv(m_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max1) ); + + GLint maxLength = uint32_max(max0, max1); + char* name = (char*)g_realloc(NULL, maxLength + 1); + + BX_TRACE("Program %d", m_id); + BX_TRACE("Attributes:"); + for (int32_t ii = 0; ii < activeAttribs; ++ii) + { + GLint size; + GLenum type; + + GL_CHECK(glGetActiveAttrib(m_id, ii, maxLength + 1, NULL, &size, &type, name) ); + BX_TRACE("\t%s %s is at location %d" + , glslTypeName(type) + , name + , glGetAttribLocation(m_id, name) + ); + } + + m_numPredefined = 0; + m_constantBuffer = ConstantBuffer::create(1024); + m_numSamplers = 0; + + BX_TRACE("Uniforms:"); + for (int32_t ii = 0; ii < activeUniforms; ++ii) + { + GLint num; + GLenum gltype; + + GL_CHECK(glGetActiveUniform(m_id, ii, maxLength + 1, NULL, &num, &gltype, name) ); + GLint loc = glGetUniformLocation(m_id, name); + + int offset = 0; + char* array = strchr(name, '['); + if (NULL != array) + { + BX_TRACE("--- %s", name); + *array = '\0'; + array++; + char* end = strchr(array, ']'); + *end = '\0'; + offset = atoi(array); + } + + if (GL_SAMPLER_2D == gltype) + { + BX_TRACE("Sampler %d at %d.", m_numSamplers, loc); + m_sampler[m_numSamplers] = loc; + m_numSamplers++; + } + + const void* data = NULL; + PredefinedUniform::Enum predefined = nameToPredefinedUniformEnum(name); + if (PredefinedUniform::Count != predefined) + { + m_predefined[m_numPredefined].m_loc = loc; + m_predefined[m_numPredefined].m_type = predefined; + m_predefined[m_numPredefined].m_count = num; + m_numPredefined++; + } + else + { + const UniformInfo* info = s_renderCtx.m_uniformReg.find(name); + if (NULL != info) + { + data = info->m_data; + ConstantType::Enum type = convertGlType(gltype); + m_constantBuffer->writeUniformRef(type, loc, data, num); + BX_TRACE("store %s %p", name, data); + } + } + + BX_TRACE("\tuniform %s %s%s is at location %d, size %d (%p), offset %d" + , glslTypeName(gltype) + , name + , PredefinedUniform::Count != predefined ? "*" : "" + , loc + , num + , data + , offset + ); + BX_UNUSED(offset); + } + + m_constantBuffer->finish(); + + g_free(name); + + memset(m_attributes, 0xff, sizeof(m_attributes) ); + uint32_t used = 0; + for (uint32_t ii = 0; ii < Attrib::Count; ++ii) + { + GLuint loc = glGetAttribLocation(m_id, s_attribName[ii]); + if (GLuint(-1) != loc ) + { + BX_TRACE("attr %s: %d", s_attribName[ii], loc); + m_attributes[ii] = loc; + m_used[used++] = ii; + } + } + m_used[used] = Attrib::Count; + + used = 0; + for (uint32_t ii = 0; ii < countof(s_instanceDataName); ++ii) + { + GLuint loc = glGetAttribLocation(m_id, s_instanceDataName[ii]); + if (GLuint(-1) != loc ) + { + BX_TRACE("instance data %s: %d", s_instanceDataName[ii], loc); + m_instanceData[used++] = loc; + } + } + m_instanceData[used] = 0xffff; + } + + void Material::bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex) const + { + uint32_t enabled = 0; + for (uint32_t ii = 0; Attrib::Count != m_used[ii]; ++ii) + { + Attrib::Enum attr = Attrib::Enum(m_used[ii]); + GLuint loc = m_attributes[attr]; + + uint8_t num; + AttribType::Enum type; + bool normalized; + _vertexDecl.decode(attr, num, type, normalized); + + if (0xffff != loc + && 0xff != _vertexDecl.m_attributes[attr]) + { + GL_CHECK(glEnableVertexAttribArray(loc) ); + enabled |= 1< 1) + { + m_target = GL_TEXTURE_3D; + } +#endif // BGFX_CONFIG_RENDERER_OPENGL + else + { + m_target = GL_TEXTURE_2D; + } + + GL_CHECK(glGenTextures(1, &m_id) ); + BX_CHECK(0 != m_id, "Failed to generate texture id."); + GL_CHECK(glBindTexture(m_target, m_id) ); + + const TextureFormatInfo& tfi = s_textureFormat[dds.m_type]; + GLenum internalFmt = tfi.m_internalFmt; + GLenum fmt = tfi.m_format; + + GLenum target = m_target; + if (dds.m_cubeMap) + { + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + } + + if (!s_renderCtx.m_dxtSupport + || TextureFormat::Unknown < dds.m_type) + { + if (GL_RGBA == internalFmt) + { + internalFmt = s_extension[Extension::EXT_texture_format_BGRA8888].m_supported ? GL_BGRA_EXT : GL_RGBA; + fmt = internalFmt; + } + + uint8_t* bits = (uint8_t*)g_realloc(NULL, dds.m_width*dds.m_height*tfi.m_bpp); + + for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side) + { + uint32_t width = dds.m_width; + uint32_t height = dds.m_height; + uint32_t depth = dds.m_depth; + + for (uint32_t lod = 0, num = dds.m_numMips; lod < num; ++lod) + { + width = uint32_max(1, width); + height = uint32_max(1, height); + depth = uint32_max(1, depth); + + Mip mip; + if (getRawImageData(dds, 0, lod, _mem, mip) ) + { + mip.decode(bits); + + if (GL_RGBA == internalFmt) + { + uint32_t dstpitch = width*4; + for (uint32_t yy = 0; yy < height; ++yy) + { + uint8_t* dst = &bits[yy*dstpitch]; + + for (uint32_t xx = 0; xx < width; ++xx) + { + uint8_t tmp = dst[0]; + dst[0] = dst[2]; + dst[2] = tmp; + dst += 4; + } + } + } + +#if BGFX_CONFIG_RENDERER_OPENGL + if (target == GL_TEXTURE_3D) + { + GL_CHECK(glTexImage3D(target + , lod + , internalFmt + , width + , height + , depth + , 0 + , fmt + , tfi.m_type + , bits + ) ); + } + else +#endif // BGFX_CONFIG_RENDERER_OPENGL + { + GL_CHECK(glTexImage2D(target+side + , lod + , internalFmt + , width + , height + , 0 + , fmt + , tfi.m_type + , bits + ) ); + } + } + + width >>= 1; + height >>= 1; + depth >>= 1; + } + } + + g_free(bits); + } + else + { + for (uint8_t side = 0, numSides = dds.m_cubeMap ? 6 : 1; side < numSides; ++side) + { + uint32_t width = dds.m_width; + uint32_t height = dds.m_height; + uint32_t depth = dds.m_depth; + + for (uint32_t ii = 0, num = dds.m_numMips; ii < num; ++ii) + { + width = uint32_max(1, width); + height = uint32_max(1, height); + depth = uint32_max(1, depth); + + Mip mip; + if (getRawImageData(dds, 0, ii, _mem, mip) ) + { +#if BGFX_CONFIG_RENDERER_OPENGL + if (m_target == GL_TEXTURE_3D) + { + GL_CHECK(glCompressedTexImage3D(target + , ii + , internalFmt + , width + , height + , depth + , 0 + , mip.m_size + , mip.m_data + ) ); + } + else +#endif // BGFX_CONFIG_RENDERER_OPENGL + { + GL_CHECK(glCompressedTexImage2D(target+side + , ii + , internalFmt + , width + , height + , 0 + , mip.m_size + , mip.m_data + ) ); + } + } + + width >>= 1; + height >>= 1; + depth >>= 1; + } + } + } + + } + else + { + m_target = GL_TEXTURE_2D; + GL_CHECK(glGenTextures(1, &m_id) ); + BX_CHECK(0 != m_id, "Failed to generate texture id."); + GL_CHECK(glBindTexture(m_target, m_id) ); + + StreamRead stream(_mem->data, _mem->size); + + uint32_t magic; + stream.read(magic); + + if (BGFX_MAGIC == magic) + { + uint16_t width; + stream.read(width); + + uint16_t height; + stream.read(height); + + uint8_t bpp; + stream.read(bpp); + + stream.read(numMips); + + stream.align(16); + + for (uint8_t mip = 0; mip < numMips; ++mip) + { + width = uint32_max(width, 1); + height = uint32_max(height, 1); + + const uint8_t* data = stream.getDataPtr(); + stream.skip(width*height*bpp); + + GL_CHECK(glTexImage2D(m_target + , mip + , 1 == bpp ? GL_LUMINANCE : GL_RGBA + , width + , height + , 0 + , 1 == bpp ? GL_LUMINANCE : GL_RGBA + , GL_UNSIGNED_BYTE + , data + ) ); + + width >>= 1; + height >>= 1; + } + } + else + { + // + } + } + + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, s_textureAddress[(_flags&BGFX_TEXTURE_U_MASK)>>BGFX_TEXTURE_U_SHIFT]) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, s_textureAddress[(_flags&BGFX_TEXTURE_V_MASK)>>BGFX_TEXTURE_V_SHIFT]) ); + +#if BGFX_CONFIG_RENDERER_OPENGL + if (m_target == GL_TEXTURE_3D) + { + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_R, s_textureAddress[(_flags&BGFX_TEXTURE_W_MASK)>>BGFX_TEXTURE_W_SHIFT]) ); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL + + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, s_textureFilter[(_flags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, 1 < numMips ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) ); + + GL_CHECK(glBindTexture(m_target, 0) ); + } + + void Texture::createColor(uint32_t _width, uint32_t _height, GLenum _min, GLenum _mag) + { + GLenum internalFormat = /*_fp ? GL_RGBA16F_ARB :*/ GL_RGBA; + GLenum type = /*_fp ? GL_HALF_FLOAT_ARB :*/ GL_UNSIGNED_BYTE; + m_target = /*0 != _depth ? GL_TEXTURE_3D :*/ GL_TEXTURE_2D; + + GL_CHECK(glGenTextures(1, &m_id) ); + BX_CHECK(0 != m_id, "Failed to generate texture id."); + GL_CHECK(glBindTexture(m_target, m_id) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, _min) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, _mag) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) ); + + GL_CHECK(glTexImage2D(m_target + , 0 + , internalFormat + , _width + , _height + , 0 + , GL_RGBA + , type + , NULL + ) ); + + GL_CHECK(glBindTexture(m_target, 0) ); + } + + void Texture::createDepth(uint32_t _width, uint32_t _height) + { + m_target = GL_TEXTURE_2D; + + GL_CHECK(glGenTextures(1, &m_id) ); + BX_CHECK(0 != m_id, "Failed to generate texture id."); + GL_CHECK(glBindTexture(m_target, m_id) ); +// glTexParameteri(m_target, GL_TEXTURE_COMPARE_MODE, GL_NONE); +// glTexParameteri(m_target, GL_DEPTH_TEXTURE_MODE, GL_NONE); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) ); + GL_CHECK(glTexParameteri(m_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) ); + + // OpenGL ES 2.0 doesn't support GL_DEPTH_COMPONENT... this will fail. + GL_CHECK(glTexImage2D(m_target + , 0 + , GL_DEPTH_COMPONENT + , _width + , _height + , 0 + , GL_DEPTH_COMPONENT + , GL_FLOAT + , NULL + ) ); + + GL_CHECK(glBindTexture(m_target, 0) ); + } + + void Texture::destroy() + { + if (0 != m_id) + { + GL_CHECK(glBindTexture(m_target, 0) ); + GL_CHECK(glDeleteTextures(1, &m_id) ); + m_id = 0; + } + } + + void RenderTarget::create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) + { + BX_TRACE("Create render target %dx%d 0x%02x", _width, _height, _flags); + + m_width = _width; + m_height = _height; + +// m_msaa = s_msaa[(m_flags&BGFX_RENDER_TARGET_MSAA_MASK)>>BGFX_RENDER_TARGET_MSAA_SHIFT]; + uint32_t colorFormat = (_flags&BGFX_RENDER_TARGET_COLOR_MASK)>>BGFX_RENDER_TARGET_COLOR_SHIFT; + uint32_t depthFormat = (_flags&BGFX_RENDER_TARGET_DEPTH_MASK)>>BGFX_RENDER_TARGET_DEPTH_SHIFT; + GLenum minFilter = s_textureFilter[(_textureFlags&BGFX_TEXTURE_MIN_MASK)>>BGFX_TEXTURE_MIN_SHIFT]; + GLenum magFilter = s_textureFilter[(_textureFlags&BGFX_TEXTURE_MAG_MASK)>>BGFX_TEXTURE_MAG_SHIFT]; + + if (0 < colorFormat) + { + m_color.createColor(_width, _height, minFilter, magFilter); + } + +#if 0 // GLES can't create texture with depth texture format... + if (0 < depthFormat) + { + m_depth.createDepth(_width, _height); + } +#endif // + + GL_CHECK(glGenFramebuffers(1, &m_fbo) ); + BX_CHECK(0 != m_fbo, "Failed to generate framebuffer id."); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_fbo) ); + + if (0 < colorFormat) + { + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER + , GL_COLOR_ATTACHMENT0 + , m_color.m_target + , m_color.m_id + , 0 + ) ); + } + + if (0 < depthFormat) + { + if (0 < colorFormat) + { +#if BGFX_CONFIG_RENDERER_OPENGL + GLenum depthComponent = GL_DEPTH_COMPONENT32; +#else + GLenum depthComponent = GL_DEPTH_COMPONENT16; +#endif // BGFX_CONFIG_RENDERER_OPENGL + + GL_CHECK(glGenRenderbuffers(1, &m_rbo) ); + BX_CHECK(0 != m_rbo, "Failed to generate renderbuffer id."); + GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, m_rbo) ); + GL_CHECK(glRenderbufferStorage(GL_RENDERBUFFER, depthComponent, _width, _height) ); + GL_CHECK(glBindRenderbuffer(GL_RENDERBUFFER, 0) ); + + GL_CHECK(glFramebufferRenderbuffer(GL_FRAMEBUFFER + , GL_DEPTH_ATTACHMENT + , GL_RENDERBUFFER + , m_rbo + ) ); + } + else + { + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER + , GL_DEPTH_ATTACHMENT + , m_depth.m_target + , m_depth.m_id + , 0 + ) ); + } + } + + BX_CHECK(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_FRAMEBUFFER) + ); + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + } + + void RenderTarget::destroy() + { + GL_CHECK(glDeleteFramebuffers(1, &m_fbo) ); + + if (0 != m_rbo) + { + GL_CHECK(glDeleteRenderbuffers(1, &m_rbo) ); + } + + m_color.destroy(); + m_depth.destroy(); + } + + void ConstantBuffer::commit() + { + reset(); + + do + { + uint32_t opcode = read(); + + if (ConstantType::End == opcode) + { + break; + } + + ConstantType::Enum type; + uint16_t loc; + uint16_t num; + uint16_t copy; + decodeOpcode(opcode, type, loc, num, copy); + + const char* data; + if (copy) + { + data = read(g_constantTypeSize[type]*num); + } + else + { + memcpy(&data, read(sizeof(void*) ), sizeof(void*) ); + } + +#define CASE_IMPLEMENT_UNIFORM(_uniform, _glsuffix, _dxsuffix, _type) \ + case ConstantType::_uniform: \ + { \ + _type* value = (_type*)data; \ + GL_CHECK(glUniform##_glsuffix(loc, num, value) ); \ + } \ + break; + +#define CASE_IMPLEMENT_UNIFORM_T(_uniform, _glsuffix, _dxsuffix, _type) \ + case ConstantType::_uniform: \ + { \ + _type* value = (_type*)data; \ + GL_CHECK(glUniform##_glsuffix(loc, num, GL_FALSE, value) ); \ + } \ + break; + + switch (type) + { +// case ConstantType::Uniform1iv: +// { +// int* value = (int*)data; +// BX_TRACE("Uniform1iv sampler %d, loc %d (num %d, copy %d)", *value, loc, num, copy); +// GL_CHECK(glUniform1iv(loc, num, value) ); +// } +// break; +// + + CASE_IMPLEMENT_UNIFORM(Uniform1i, 1iv, I, int); + CASE_IMPLEMENT_UNIFORM(Uniform1f, 1fv, F, float); + CASE_IMPLEMENT_UNIFORM(Uniform1iv, 1iv, I, int); + CASE_IMPLEMENT_UNIFORM(Uniform1fv, 1fv, F, float); + CASE_IMPLEMENT_UNIFORM(Uniform2fv, 2fv, F, float); + CASE_IMPLEMENT_UNIFORM(Uniform3fv, 3fv, F, float); + CASE_IMPLEMENT_UNIFORM(Uniform4fv, 4fv, F, float); + CASE_IMPLEMENT_UNIFORM_T(Uniform3x3fv, Matrix3fv, F, float); + CASE_IMPLEMENT_UNIFORM_T(Uniform4x4fv, Matrix4fv, F, float); + + case ConstantType::End: + break; + + default: + BX_TRACE("%4d: INVALID 0x%08x, t %d, l %d, n %d, c %d", m_pos, opcode, type, loc, num, copy); + break; + } + +#undef CASE_IMPLEMENT_UNIFORM +#undef CASE_IMPLEMENT_UNIFORM_T + + } while (true); + } + + void TextVideoMemBlitter::setup() + { + uint32_t width = s_renderCtx.m_resolution.m_width; + uint32_t height = s_renderCtx.m_resolution.m_height; + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + GL_CHECK(glViewport(0, 0, width, height) ); + + GL_CHECK(glDisable(GL_DEPTH_TEST) ); + GL_CHECK(glDepthFunc(GL_ALWAYS) ); + GL_CHECK(glDisable(GL_CULL_FACE) ); + GL_CHECK(glDisable(GL_BLEND) ); + GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) ); +#if BGFX_CONFIG_RENDERER_OPENGL + GL_CHECK(glDisable(GL_ALPHA_TEST) ); +#endif // BGFX_CONFIG_RENDERER_OPENGL + + Material& material = s_renderCtx.m_materials[m_material.idx]; + GL_CHECK(glUseProgram(material.m_id) ); + GL_CHECK(glUniform1i(material.m_sampler[0], 0) ); + + float proj[16]; + matrix_ortho(proj, 0.0f, (float)width, (float)height, 0.0f, 0.0f, 1000.0f); + + GL_CHECK(glUniformMatrix4fv(material.m_predefined[0].m_loc + , 1 + , GL_FALSE + , proj + ) ); + + GL_CHECK(glActiveTexture(GL_TEXTURE0) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, s_renderCtx.m_textures[m_texture.idx].m_id) ); + } + + void TextVideoMemBlitter::render(uint32_t _numIndices) + { + uint32_t numVertices = _numIndices*4/6; + s_renderCtx.m_indexBuffers[m_ib->handle.idx].update(0, _numIndices*2, m_ib->data); + s_renderCtx.m_vertexBuffers[m_vb->handle.idx].update(0, numVertices*m_decl.m_stride, m_vb->data); + + VertexBuffer& vb = s_renderCtx.m_vertexBuffers[m_vb->handle.idx]; + GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); + + IndexBuffer& ib = s_renderCtx.m_indexBuffers[m_ib->handle.idx]; + GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) ); + + Material& material = s_renderCtx.m_materials[m_material.idx]; + material.bindAttributes(m_decl, 0); + + GL_CHECK(glDrawElements(GL_TRIANGLES + , _numIndices + , GL_UNSIGNED_SHORT + , (void*)0 + ) ); + } + + void Context::flip() + { + s_renderCtx.flip(); + } + + GLint glGet(GLenum _pname) + { + GLint result; + GL_CHECK(glGetIntegerv(_pname, &result) ); + return result; + } + + void Context::rendererInit() + { + s_renderCtx.init(); + +#if BGFX_CONFIG_DEBUG + GLint numCmpFormats; + GL_CHECK(glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCmpFormats) ); + + BX_TRACE("GL_NUM_COMPRESSED_TEXTURE_FORMATS %d", numCmpFormats); + + GLint* formats = (GLint*)alloca(sizeof(GLint)*numCmpFormats); + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, formats); + + for (GLint ii = 0; ii < numCmpFormats; ++ii) + { + BX_TRACE("\t%3d: %8x", ii, formats[ii]); + } + +# define GL_GET(_pname, _min) BX_TRACE(#_pname " %d (min: %d)", glGet(_pname), _min) + + GL_GET(GL_MAX_FRAGMENT_UNIFORM_VECTORS, 16); + GL_GET(GL_MAX_VERTEX_UNIFORM_VECTORS, 128); + GL_GET(GL_MAX_VARYING_VECTORS, 8); + GL_GET(GL_MAX_VERTEX_ATTRIBS, 8); + GL_GET(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 8); + GL_GET(GL_MAX_CUBE_MAP_TEXTURE_SIZE, 16); + GL_GET(GL_MAX_TEXTURE_IMAGE_UNITS, 8); + GL_GET(GL_MAX_TEXTURE_SIZE, 64); + GL_GET(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, 0); + GL_GET(GL_MAX_RENDERBUFFER_SIZE, 1); +#endif // BGFX_CONFIG_DEBUG + + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + + char name[1024]; + const char* pos = extensions; + const char* end = extensions + strlen(extensions); + while (pos < end) + { + uint32_t len; + const char* space = strchr(pos, ' '); + if (NULL != space) + { + len = uint32_min(sizeof(name), (uint32_t)(space - pos) ); + } + else + { + len = uint32_min(sizeof(name), (uint32_t)strlen(pos) ); + } + + strncpy(name, pos, len); + name[len] = '\0'; + + bool supported = false; + for (uint32_t ii = 0; ii < Extension::Count; ++ii) + { + Extension& extension = s_extension[ii]; + if (!extension.m_supported + && extension.m_initialize) + { + if (0 == strcmp(name, extension.m_name) ) + { + extension.m_supported = true; + supported = true; + break; + } + } + } + + BX_TRACE("GL_EXTENSION%s: %s", supported ? " (supported)" : "", name); + BX_UNUSED(supported); + + pos += len+1; + } + + BX_TRACE("Supported extensions:"); + for (uint32_t ii = 0; ii < Extension::Count; ++ii) + { + if (s_extension[ii].m_supported) + { + BX_TRACE("\t%2d: %s", ii, s_extension[ii].m_name); + } + } + + s_renderCtx.m_dxtSupport = true + && s_extension[Extension::EXT_texture_compression_dxt1].m_supported + && s_extension[Extension::CHROMIUM_texture_compression_dxt3].m_supported + && s_extension[Extension::CHROMIUM_texture_compression_dxt5].m_supported + ; + + s_renderCtx.m_dxtSupport |= + s_extension[Extension::EXT_texture_compression_s3tc].m_supported + ; + } + + void Context::rendererShutdown() + { + s_renderCtx.shutdown(); + } + + void Context::rendererCreateIndexBuffer(IndexBufferHandle _handle, Memory* _mem) + { + s_renderCtx.m_indexBuffers[_handle.idx].create(_mem->size, _mem->data); + } + + void Context::rendererDestroyIndexBuffer(IndexBufferHandle _handle) + { + s_renderCtx.m_indexBuffers[_handle.idx].destroy(); + } + + void Context::rendererCreateVertexDecl(VertexDeclHandle _handle, const VertexDecl& _decl) + { + VertexDecl& decl = s_renderCtx.m_vertexDecls[_handle.idx]; + memcpy(&decl, &_decl, sizeof(VertexDecl) ); + dump(decl); + } + + void Context::rendererDestroyVertexDecl(VertexDeclHandle /*_handle*/) + { + } + + void Context::rendererCreateVertexBuffer(VertexBufferHandle _handle, Memory* _mem, VertexDeclHandle _declHandle) + { + s_renderCtx.m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _declHandle); + } + + void Context::rendererDestroyVertexBuffer(VertexBufferHandle _handle) + { + s_renderCtx.m_vertexBuffers[_handle.idx].destroy(); + } + + void Context::rendererCreateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _size) + { + s_renderCtx.m_indexBuffers[_handle.idx].create(_size, NULL); + } + + void Context::rendererUpdateDynamicIndexBuffer(IndexBufferHandle _handle, uint32_t _offset, uint32_t _size, Memory* _mem) + { + s_renderCtx.m_indexBuffers[_handle.idx].update(_offset, uint32_min(_size, _mem->size), _mem->data); + } + + void Context::rendererDestroyDynamicIndexBuffer(IndexBufferHandle _handle) + { + s_renderCtx.m_indexBuffers[_handle.idx].destroy(); + } + + void Context::rendererCreateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size) + { + VertexDeclHandle decl = BGFX_INVALID_HANDLE; + s_renderCtx.m_vertexBuffers[_handle.idx].create(_size, NULL, decl); + } + + void Context::rendererUpdateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, Memory* _mem) + { + s_renderCtx.m_vertexBuffers[_handle.idx].update(_offset, uint32_min(_size, _mem->size), _mem->data); + } + + void Context::rendererDestroyDynamicVertexBuffer(VertexBufferHandle _handle) + { + s_renderCtx.m_vertexBuffers[_handle.idx].destroy(); + } + + void Context::rendererCreateVertexShader(VertexShaderHandle _handle, Memory* _mem) + { + s_renderCtx.m_vertexShaders[_handle.idx].create(GL_VERTEX_SHADER, _mem->data); + } + + void Context::rendererDestroyVertexShader(VertexShaderHandle _handle) + { + s_renderCtx.m_vertexShaders[_handle.idx].destroy(); + } + + void Context::rendererCreateFragmentShader(FragmentShaderHandle _handle, Memory* _mem) + { + s_renderCtx.m_fragmentShaders[_handle.idx].create(GL_FRAGMENT_SHADER, _mem->data); + } + + void Context::rendererDestroyFragmentShader(FragmentShaderHandle _handle) + { + s_renderCtx.m_fragmentShaders[_handle.idx].destroy(); + } + + void Context::rendererCreateMaterial(MaterialHandle _handle, VertexShaderHandle _vsh, FragmentShaderHandle _fsh) + { + s_renderCtx.m_materials[_handle.idx].create(s_renderCtx.m_vertexShaders[_vsh.idx], s_renderCtx.m_fragmentShaders[_fsh.idx]); + } + + void Context::rendererDestroyMaterial(FragmentShaderHandle _handle) + { + s_renderCtx.m_materials[_handle.idx].destroy(); + } + + void Context::rendererCreateTexture(TextureHandle _handle, Memory* _mem, uint32_t _flags) + { + s_renderCtx.m_textures[_handle.idx].create(_mem, _flags); + } + + void Context::rendererDestroyTexture(TextureHandle _handle) + { + s_renderCtx.m_textures[_handle.idx].destroy(); + } + + void Context::rendererCreateRenderTarget(RenderTargetHandle _handle, uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags) + { + s_renderCtx.m_renderTargets[_handle.idx].create(_width, _height, _flags, _textureFlags); + } + + void Context::rendererDestroyRenderTarget(RenderTargetHandle _handle) + { + s_renderCtx.m_renderTargets[_handle.idx].destroy(); + } + + void Context::rendererCreateUniform(UniformHandle _handle, ConstantType::Enum _type, uint16_t _num, const char* _name) + { + uint32_t size = g_constantTypeSize[_type]*_num; + void* data = g_realloc(NULL, size); + s_renderCtx.m_uniforms[_handle.idx] = data; + s_renderCtx.m_uniformReg.reg(_name, s_renderCtx.m_uniforms[_handle.idx]); + } + + void Context::rendererDestroyUniform(UniformHandle _handle) + { + g_free(s_renderCtx.m_uniforms[_handle.idx]); + } + + void Context::rendererSaveScreenShot(Memory* _mem) + { + s_renderCtx.saveScreenShot(_mem); + } + + void Context::rendererUpdateUniform(uint16_t _loc, const void* _data, uint32_t _size) + { + memcpy(s_renderCtx.m_uniforms[_loc], _data, _size); + } + + void Context::rendererSubmit() + { + s_renderCtx.updateResolution(m_render->m_resolution); + + int64_t elapsed = -bx::getHPCounter(); +#if BGFX_CONFIG_RENDERER_OPENGL + if (m_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) + { + s_renderCtx.m_queries.begin(0, GL_TIME_ELAPSED); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL + + if (0 < m_render->m_iboffset) + { + TransientIndexBuffer* ib = m_render->m_transientIb; + s_renderCtx.m_indexBuffers[ib->handle.idx].update(0, m_render->m_iboffset, ib->data); + } + + if (0 < m_render->m_vboffset) + { + TransientVertexBuffer* vb = m_render->m_transientVb; + s_renderCtx.m_vertexBuffers[vb->handle.idx].update(0, m_render->m_vboffset, vb->data); + } + + m_render->sort(); + + RenderState currentState; + currentState.reset(); + currentState.m_flags = BGFX_STATE_NONE; + + Matrix4 viewProj[BGFX_CONFIG_MAX_VIEWS]; + for (uint32_t ii = 0; ii < BGFX_CONFIG_MAX_VIEWS; ++ii) + { + matrix_mul(viewProj[ii].val, m_render->m_view[ii].val, m_render->m_proj[ii].val); + } + + uint16_t materialIdx = bgfx::invalidHandle; + SortKey key; + uint8_t view = 0xff; + RenderTargetHandle rt = BGFX_INVALID_HANDLE; + int32_t height = m_render->m_resolution.m_height; + float alphaRef = 0.0f; + GLenum primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : GL_TRIANGLES; + uint32_t primNumVerts = 3; + uint32_t baseVertex = 0; + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + + uint32_t statsNumPrimsSubmitted = 0; + uint32_t statsNumIndices = 0; + uint32_t statsNumInstances = 0; + uint32_t statsNumPrimsRendered = 0; + + if (0 == (m_render->m_debug&BGFX_DEBUG_IFH) ) + { + for (uint32_t item = 0, numItems = m_render->m_num; item < numItems; ++item) + { + key.decode(m_render->m_sortKeys[item]); + const RenderState& state = m_render->m_renderState[m_render->m_sortValues[item] ]; + + const uint64_t newFlags = state.m_flags; + uint64_t changedFlags = currentState.m_flags ^ state.m_flags; + currentState.m_flags = newFlags; + + if (key.m_view != view) + { + currentState.clear(); + changedFlags = BGFX_STATE_MASK; + currentState.m_flags = newFlags; + + GREMEDY_SETMARKER("view"); + + view = key.m_view; + materialIdx = bgfx::invalidHandle; + + if (m_render->m_rt[view].idx != rt.idx) + { + rt = m_render->m_rt[view]; + + if (rt.idx == bgfx::invalidHandle) + { + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + height = m_render->m_resolution.m_height; + } + else + { + RenderTarget& renderTarget = s_renderCtx.m_renderTargets[rt.idx]; + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, renderTarget.m_fbo) ); + height = renderTarget.m_height; + } + } + + Rect& rect = m_render->m_rect[view]; + + GL_CHECK(glViewport(rect.m_x, height-rect.m_height-rect.m_y, rect.m_width, rect.m_height) ); + + Clear& clear = m_render->m_clear[view]; + + if (BGFX_CLEAR_NONE != clear.m_flags) + { + GLuint flags = 0; + if (BGFX_CLEAR_COLOR_BIT & clear.m_flags) + { + flags |= GL_COLOR_BUFFER_BIT; + uint32_t rgba = clear.m_rgba; + float rr = (rgba>>24)/255.0f; + float gg = ( (rgba>>16)&0xff)/255.0f; + float bb = ( (rgba>>8)&0xff)/255.0f; + float aa = (rgba&0xff)/255.0f; + GL_CHECK(glClearColor(rr, gg, bb, aa) ); + GL_CHECK(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) ); + } + + if (BGFX_CLEAR_DEPTH_BIT & clear.m_flags) + { + flags |= GL_DEPTH_BUFFER_BIT; + GL_CHECK(glClearDepthf(clear.m_depth) ); + GL_CHECK(glDepthMask(GL_TRUE) ); + } + + if (BGFX_CLEAR_STENCIL_BIT & clear.m_flags) + { + flags |= GL_STENCIL_BUFFER_BIT; + GL_CHECK(glClearStencil(clear.m_stencil) ); + } + + if (0 != flags) + { + GL_CHECK(glEnable(GL_SCISSOR_TEST) ); + GL_CHECK(glScissor(rect.m_x, height-rect.m_height-rect.m_y, rect.m_width, rect.m_height) ); + GL_CHECK(glClear(flags) ); + GL_CHECK(glDisable(GL_SCISSOR_TEST) ); + } + } + + GL_CHECK(glEnable(GL_DEPTH_TEST) ); + GL_CHECK(glDepthFunc(GL_LESS) ); + GL_CHECK(glEnable(GL_CULL_FACE) ); + GL_CHECK(glDisable(GL_BLEND) ); + } + + if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK + |BGFX_STATE_ALPHA_MASK|BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE + |BGFX_STATE_BLEND_MASK|BGFX_STATE_ALPHA_REF_MASK|BGFX_STATE_PT_MASK + |BGFX_STATE_POINT_SIZE_MASK) & changedFlags) + { + if (BGFX_STATE_CULL_MASK & changedFlags) + { + if (BGFX_STATE_CULL_CW & newFlags) + { + GL_CHECK(glEnable(GL_CULL_FACE) ); + GL_CHECK(glCullFace(GL_BACK) ); + } + else if (BGFX_STATE_CULL_CCW & newFlags) + { + GL_CHECK(glEnable(GL_CULL_FACE) ); + GL_CHECK(glCullFace(GL_FRONT) ); + } + else + { + GL_CHECK(glDisable(GL_CULL_FACE) ); + } + } + + if (BGFX_STATE_DEPTH_WRITE & changedFlags) + { + GL_CHECK(glDepthMask(!!(BGFX_STATE_DEPTH_WRITE & newFlags) ) ); + } + + if (BGFX_STATE_DEPTH_TEST_MASK & changedFlags) + { + uint32_t func = (newFlags&BGFX_STATE_DEPTH_TEST_MASK)>>BGFX_STATE_DEPTH_TEST_SHIFT; + + if (0 != func) + { + GL_CHECK(glEnable(GL_DEPTH_TEST) ); + GL_CHECK(glDepthFunc(s_depthFunc[func]) ); + } + else + { + GL_CHECK(glDisable(GL_DEPTH_TEST) ); + } + } + + if ( (BGFX_STATE_ALPHA_TEST|BGFX_STATE_ALPHA_REF_MASK) & changedFlags) + { + uint32_t ref = (newFlags&BGFX_STATE_ALPHA_REF_MASK)>>BGFX_STATE_ALPHA_REF_SHIFT; + alphaRef = ref/255.0f; + +#if BGFX_CONFIG_RENDERER_OPENGL + if (BGFX_STATE_ALPHA_TEST & newFlags) + { + GL_CHECK(glEnable(GL_ALPHA_TEST) ); + } + else + { + GL_CHECK(glDisable(GL_ALPHA_TEST) ); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL + } + +#if BGFX_CONFIG_RENDERER_OPENGL + if ( (BGFX_STATE_PT_POINTS|BGFX_STATE_POINT_SIZE_MASK) & changedFlags) + { + float pointSize = (float)(uint32_max(1, (newFlags&BGFX_STATE_POINT_SIZE_MASK)>>BGFX_STATE_POINT_SIZE_SHIFT) ); + GL_CHECK(glPointSize(pointSize) ); + } +#endif // BGFX_CONFIG_RENDERER_OPENGL + + if ( (BGFX_STATE_ALPHA_WRITE|BGFX_STATE_RGB_WRITE) & changedFlags) + { + GLboolean alpha = !!(newFlags&BGFX_STATE_ALPHA_WRITE); + GLboolean rgb = !!(newFlags&BGFX_STATE_RGB_WRITE); + GL_CHECK(glColorMask(rgb, rgb, rgb, alpha) ); + } + + if (BGFX_STATE_BLEND_MASK & changedFlags) + { + if (BGFX_STATE_BLEND_MASK & newFlags) + { + uint32_t blend = (newFlags&BGFX_STATE_BLEND_MASK)>>BGFX_STATE_BLEND_SHIFT; + uint32_t src = blend&0xf; + uint32_t dst = (blend>>4)&0xf; + GL_CHECK(glEnable(GL_BLEND) ); + GL_CHECK(glBlendFunc(s_blendFactor[src], s_blendFactor[dst]) ); + } + else + { + GL_CHECK(glDisable(GL_BLEND) ); + } + } + + uint8_t primIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT); + primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : s_primType[primIndex]; + primNumVerts = s_primNumVerts[primIndex]; + } + + bool materialChanged = false; + bool constantsChanged = state.m_constBegin < state.m_constEnd; + bool bindAttribs = false; + rendererUpdateUniforms(m_render->m_constantBuffer, state.m_constBegin, state.m_constEnd); + + if (key.m_material != materialIdx) + { + materialIdx = key.m_material; + GLuint id = bgfx::invalidHandle == materialIdx ? 0 : s_renderCtx.m_materials[materialIdx].m_id; + GL_CHECK(glUseProgram(id) ); + materialChanged = + constantsChanged = + bindAttribs = true; + } + + if (bgfx::invalidHandle != materialIdx) + { + Material& material = s_renderCtx.m_materials[materialIdx]; + + if (constantsChanged) + { + material.m_constantBuffer->commit(); + } + + for (uint32_t ii = 0, num = material.m_numPredefined; ii < num; ++ii) + { + PredefinedUniform& predefined = material.m_predefined[ii]; + switch (predefined.m_type) + { + case PredefinedUniform::ViewRect: + { + float rect[4]; + rect[0] = m_render->m_rect[view].m_x; + rect[1] = m_render->m_rect[view].m_y; + rect[2] = m_render->m_rect[view].m_width; + rect[3] = m_render->m_rect[view].m_height; + + GL_CHECK(glUniform4fv(predefined.m_loc + , 1 + , &rect[0] + ) ); + } + break; + + case PredefinedUniform::ViewTexel: + { + float rect[4]; + rect[0] = 1.0f/float(m_render->m_rect[view].m_width); + rect[1] = 1.0f/float(m_render->m_rect[view].m_height); + + GL_CHECK(glUniform4fv(predefined.m_loc + , 1 + , &rect[0] + ) ); + } + break; + + case PredefinedUniform::View: + { + GL_CHECK(glUniformMatrix4fv(predefined.m_loc + , 1 + , GL_FALSE + , m_render->m_view[view].val + ) ); + } + break; + + case PredefinedUniform::ViewProj: + { + GL_CHECK(glUniformMatrix4fv(predefined.m_loc + , 1 + , GL_FALSE + , viewProj[view].val + ) ); + } + break; + + case PredefinedUniform::Model: + { + const Matrix4& model = m_render->m_matrixCache.m_cache[state.m_matrix]; + GL_CHECK(glUniformMatrix4fv(predefined.m_loc + , uint32_min(predefined.m_count, state.m_num) + , GL_FALSE + , model.val + ) ); + } + break; + + case PredefinedUniform::ModelViewProj: + { + Matrix4 modelViewProj; + const Matrix4& model = m_render->m_matrixCache.m_cache[state.m_matrix]; + matrix_mul(modelViewProj.val, model.val, viewProj[view].val); + + GL_CHECK(glUniformMatrix4fv(predefined.m_loc + , 1 + , GL_FALSE + , modelViewProj.val + ) ); + } + break; + + case PredefinedUniform::ModelViewProjX: + { + const Matrix4& model = m_render->m_matrixCache.m_cache[state.m_matrix]; + + static const BX_ALIGN_STRUCT_16(float) s_bias[16] = + { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, + }; + + uint8_t other = m_render->m_other[view]; + Matrix4 viewProjBias; + matrix_mul(viewProjBias.val, viewProj[other].val, s_bias); + + Matrix4 modelViewProj; + matrix_mul(modelViewProj.val, model.val, viewProjBias.val); + + GL_CHECK(glUniformMatrix4fv(predefined.m_loc + , 1 + , GL_FALSE + , modelViewProj.val + ) ); + } + break; + + case PredefinedUniform::ViewProjX: + { + static const BX_ALIGN_STRUCT_16(float) s_bias[16] = + { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, + }; + + uint8_t other = m_render->m_other[view]; + Matrix4 viewProjBias; + matrix_mul(viewProjBias.val, viewProj[other].val, s_bias); + + GL_CHECK(glUniformMatrix4fv(predefined.m_loc + , 1 + , GL_FALSE + , viewProjBias.val + ) ); + } + break; + + case PredefinedUniform::AlphaRef: + { + GL_CHECK(glUniform1f(predefined.m_loc, alphaRef) ); + } + break; + + case PredefinedUniform::Count: + break; + } + } + +// if (BGFX_STATE_TEX_MASK & changedFlags) + { + uint64_t flag = BGFX_STATE_TEX0; + for (uint32_t stage = 0; stage < BGFX_STATE_TEX_COUNT; ++stage) + { + const Sampler& sampler = state.m_sampler[stage]; + Sampler& current = currentState.m_sampler[stage]; + if (current.m_idx != sampler.m_idx + || current.m_flags != sampler.m_flags + || materialChanged) + { + GL_CHECK(glActiveTexture(GL_TEXTURE0+stage) ); + if (bgfx::invalidHandle != sampler.m_idx) + { + switch (sampler.m_flags&BGFX_SAMPLER_TYPE_MASK) + { + case BGFX_SAMPLER_TEXTURE: + { + const Texture& texture = s_renderCtx.m_textures[sampler.m_idx]; + GL_CHECK(glBindTexture(texture.m_target, texture.m_id) ); + } + break; + + case BGFX_SAMPLER_RENDERTARGET_COLOR: + { + const RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; + GL_CHECK(glBindTexture(rt.m_color.m_target, rt.m_color.m_id) ); + } + break; + + case BGFX_SAMPLER_RENDERTARGET_DEPTH: + { + const RenderTarget& rt = s_renderCtx.m_renderTargets[sampler.m_idx]; + GL_CHECK(glBindTexture(rt.m_depth.m_target, rt.m_depth.m_id) ); + } + break; + } + } + } + + current = sampler; + flag <<= 1; + } + + GL_CHECK(glActiveTexture(GL_TEXTURE0) ); + } + + if (currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx || materialChanged) + { + currentState.m_vertexBuffer = state.m_vertexBuffer; + + uint16_t handle = state.m_vertexBuffer.idx; + if (bgfx::invalidHandle != handle) + { + VertexBuffer& vb = s_renderCtx.m_vertexBuffers[handle]; + GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); + bindAttribs = true; + } + else + { + GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); + } + } + + if (currentState.m_indexBuffer.idx != state.m_indexBuffer.idx) + { + currentState.m_indexBuffer = state.m_indexBuffer; + + uint16_t handle = state.m_indexBuffer.idx; + if (bgfx::invalidHandle != handle) + { + IndexBuffer& ib = s_renderCtx.m_indexBuffers[handle]; + GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) ); + } + else + { + GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); + } + } + + if (bgfx::invalidHandle != currentState.m_vertexBuffer.idx) + { + if (baseVertex != state.m_startVertex + || bindAttribs) + { + baseVertex = state.m_startVertex; + VertexBuffer& vb = s_renderCtx.m_vertexBuffers[state.m_vertexBuffer.idx]; + uint16_t decl = vb.m_decl.idx == bgfx::invalidHandle ? state.m_vertexDecl.idx : vb.m_decl.idx; + const Material& material = s_renderCtx.m_materials[materialIdx]; + material.bindAttributes(s_renderCtx.m_vertexDecls[decl], state.m_startVertex); + + if (invalidHandle != state.m_instanceDataBuffer.idx) + { + GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, s_renderCtx.m_vertexBuffers[state.m_instanceDataBuffer.idx].m_id) ); + material.bindInstanceData(state.m_instanceDataStride, state.m_instanceDataOffset); + } + } + + uint32_t numIndices = 0; + uint32_t numPrimsSubmitted = 0; + uint32_t numInstances = 0; + uint32_t numPrimsRendered = 0; + + if (bgfx::invalidHandle != state.m_indexBuffer.idx) + { + if (BGFX_DRAW_WHOLE_INDEX_BUFFER == state.m_startIndex) + { + numIndices = s_renderCtx.m_indexBuffers[state.m_indexBuffer.idx].m_size/2; + numPrimsSubmitted = numIndices/primNumVerts; + numInstances = state.m_numInstances; + numPrimsRendered = numPrimsSubmitted*state.m_numInstances; + + GL_CHECK(s_drawElementsInstanced(primType + , s_renderCtx.m_indexBuffers[state.m_indexBuffer.idx].m_size/2 + , GL_UNSIGNED_SHORT + , (void*)0 + , state.m_numInstances + ) ); + } + else if (primNumVerts <= state.m_numIndices) + { + numIndices = state.m_numIndices; + numPrimsSubmitted = numIndices/primNumVerts; + numInstances = state.m_numInstances; + numPrimsRendered = numPrimsSubmitted*state.m_numInstances; + + GL_CHECK(s_drawElementsInstanced(primType + , numIndices + , GL_UNSIGNED_SHORT + , (void*)(uintptr_t)(state.m_startIndex*2) + , state.m_numInstances + ) ); + } + } + else + { + numPrimsSubmitted = state.m_numVertices/primNumVerts; + numInstances = state.m_numInstances; + numPrimsRendered = numPrimsSubmitted*state.m_numInstances; + + GL_CHECK(s_drawArraysInstanced(primType + , 0 + , state.m_numVertices + , state.m_numInstances + ) ); + } + + statsNumPrimsSubmitted += numPrimsSubmitted; + statsNumIndices += numIndices; + statsNumInstances += numInstances; + statsNumPrimsRendered += numPrimsRendered; + } + } + } + } + + int64_t now = bx::getHPCounter(); + elapsed += now; + + static int64_t last = now; + int64_t frameTime = now - last; + last = now; + + if (m_render->m_debug & (BGFX_DEBUG_IFH|BGFX_DEBUG_STATS) ) + { + double elapsedGpuMs = 0.0; +#if BGFX_CONFIG_RENDERER_OPENGL + s_renderCtx.m_queries.end(GL_TIME_ELAPSED); + uint64_t elapsedGl = s_renderCtx.m_queries.getResult(0); + elapsedGpuMs = double(elapsedGl)/1e6; +#endif // BGFX_CONFIG_RENDERER_OPENGL + + TextVideoMem& tvm = s_renderCtx.m_textVideoMem; + + static int64_t next = now; + + if (now >= next) + { + next = now + bx::getHPFrequency(); + double freq = double(bx::getHPFrequency() ); + double toMs = 1000.0/freq; + double elapsedCpuMs = double(elapsed)*toMs; + + tvm.clear(); + uint16_t pos = 10; + tvm.printf(0, 0, 0x8f, " " BGFX_RENDERER_NAME " "); + tvm.printf(10, pos++, 0x8e, " Frame CPU: %3.4f [ms] / %3.2f", double(frameTime)*toMs, freq/frameTime); + tvm.printf(10, pos++, 0x8e, " Draw calls: %4d / CPU %3.4f [ms] %c GPU %3.4f [ms]" + , m_render->m_num + , elapsedCpuMs + , elapsedCpuMs > elapsedGpuMs ? '>' : '<' + , elapsedGpuMs + ); + tvm.printf(10, pos++, 0x8e, " Prims: %7d (#inst: %5d), submitted: %7d" + , statsNumPrimsRendered + , statsNumInstances + , statsNumPrimsSubmitted + ); + tvm.printf(10, pos++, 0x8e, " Indices: %7d", statsNumIndices); + tvm.printf(10, pos++, 0x8e, " DVB size: %7d", m_render->m_vboffset); + tvm.printf(10, pos++, 0x8e, " DIB size: %7d", m_render->m_iboffset); + + uint8_t attr[2] = { 0x89, 0x8a }; + uint8_t attrIndex = m_render->m_waitSubmit < m_render->m_waitRender; + + tvm.printf(10, pos++, attr[attrIndex&1], "Submit wait: %3.4f [ms]", double(m_render->m_waitSubmit)*toMs); + tvm.printf(10, pos++, attr[(attrIndex+1)&1], "Render wait: %3.4f [ms]", double(m_render->m_waitRender)*toMs); + } + + m_textVideoMemBlitter.blit(tvm); + } + else if (m_render->m_debug & BGFX_DEBUG_TEXT) + { + m_textVideoMemBlitter.blit(m_render->m_textVideoMem); + } + + GREMEDY_FRAMETERMINATOR(); + } +} + +#endif // (BGFX_CONFIG_RENDERER_OPENGLES|BGFX_CONFIG_RENDERER_OPENGL) diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 01cfc5ca4..6e8d14ddd 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -1,403 +1,403 @@ -/* - * 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__ - -#define BGFX_USE_EGL 0 -#define BGFX_USE_WGL 0 - -#if BGFX_CONFIG_RENDERER_OPENGL -# if BX_PLATFORM_LINUX -# define GL_PROTOTYPES -# define GL_GLEXT_LEGACY -# include -# include -# undef GL_PROTOTYPES -# elif BX_PLATFORM_OSX -# define GL_PROTOTYPES -# define GL_GLEXT_LEGACY -# define GL_VERSION_1_2 -# define GL_VERSION_1_3 -# define GL_VERSION_1_5 -# define GL_VERSION_2_0 -# include -# undef GL_VERSION_2_0 -# undef GL_VERSION_1_5 -# undef GL_VERSION_1_3 -# undef GL_VERSION_1_2 -# undef GL_PROTOTYPES -# else -# include -# endif // BX_PLATFORM_ - -# if BX_PLATFORM_WINDOWS -# undef BGFX_USE_WGL -# define BGFX_USE_WGL 1 -# endif // BX_PLATFORM_ - -// remove deprecated from glext.h -# define GL_VERSION_1_2_DEPRECATED -# define GL_ARB_imaging_DEPRECATED -# define GL_VERSION_1_3_DEPRECATED -# define GL_VERSION_1_4_DEPRECATED -# define GL_VERSION_1_5_DEPRECATED -# define GL_VERSION_2_0_DEPRECATED -# define GL_VERSION_2_1_DEPRECATED -// ignore everything above 2.1 -# define GL_VERSION_3_0 -# define GL_VERSION_3_0_DEPRECATED -# define GL_VERSION_3_1 -# define GL_VERSION_3_2 -# define GL_VERSION_3_3 -# define GL_VERSION_4_0 -# define GL_VERSION_4_1 -# define GL_VERSION_4_2 -# include -#elif BGFX_CONFIG_RENDERER_OPENGLES -# include -# include - -# if BX_PLATFORM_WINDOWS -# include -# undef BGFX_USE_EGL -# define BGFX_USE_EGL 1 -# endif // BX_PLATFORM_ - -# 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_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE -# define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 -# endif // GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE - -typedef void (*PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); - -#endif // BGFX_CONFIG_RENDERER_OPENGL - -#if BX_PLATFORM_NACL -# include -# include -# include -# include -#elif BX_PLATFORM_WINDOWS -# include -#elif BX_PLATFORM_LINUX -# include -#endif // BX_PLATFORM_ - -#if BGFX_CONFIG_DEBUG_GREMEDY && (BX_PLATFORM_WINDOWS || BX_PLATFORM_LINUX) -# include -#endif // BGFX_CONFIG_DEBUG_GREMEDY && (BX_PLATFORM_WINDOWS || BX_PLATFORM_LINUX) - -#if BGFX_USE_WGL -typedef PROC (APIENTRYP PFNWGLGETPROCADDRESSPROC) (LPCSTR lpszProc); -typedef BOOL (APIENTRYP PFNWGLMAKECURRENTPROC) (HDC hdc, HGLRC hglrc); -typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTPROC) (HDC hdc); -typedef BOOL (APIENTRYP PFNWGLDELETECONTEXTPROC) (HGLRC hglrc); -// -typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); -typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); -typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); -typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); -typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); -typedef void (APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -typedef void (APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func); -typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); -typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params); -typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); -typedef void (APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); -typedef void (APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); -typedef void (APIENTRYP PFNGLPOINTSIZEPROC) (GLfloat size); -typedef void (APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); -typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); -typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); -typedef void (APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s); -typedef void (APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag); -typedef void (APIENTRYP PFNGLCLEARDEPTHPROC) (GLdouble depth); -typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -#endif // BGFX_USE_WGL - -#ifndef GL_APIENTRY -# define GL_APIENTRY APIENTRY -#endif // GL_APIENTRY - -#ifndef GL_APIENTRYP -# define GL_APIENTRYP APIENTRYP -#endif // GL_APIENTRYP - -namespace bgfx -{ +/* + * 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__ + +#define BGFX_USE_EGL 0 +#define BGFX_USE_WGL 0 + +#if BGFX_CONFIG_RENDERER_OPENGL +# if BX_PLATFORM_LINUX +# define GL_PROTOTYPES +# define GL_GLEXT_LEGACY +# include +# include +# undef GL_PROTOTYPES +# elif BX_PLATFORM_OSX +# define GL_PROTOTYPES +# define GL_GLEXT_LEGACY +# define GL_VERSION_1_2 +# define GL_VERSION_1_3 +# define GL_VERSION_1_5 +# define GL_VERSION_2_0 +# include +# undef GL_VERSION_2_0 +# undef GL_VERSION_1_5 +# undef GL_VERSION_1_3 +# undef GL_VERSION_1_2 +# undef GL_PROTOTYPES +# else +# include +# endif // BX_PLATFORM_ + +# if BX_PLATFORM_WINDOWS +# undef BGFX_USE_WGL +# define BGFX_USE_WGL 1 +# endif // BX_PLATFORM_ + +// remove deprecated from glext.h +# define GL_VERSION_1_2_DEPRECATED +# define GL_ARB_imaging_DEPRECATED +# define GL_VERSION_1_3_DEPRECATED +# define GL_VERSION_1_4_DEPRECATED +# define GL_VERSION_1_5_DEPRECATED +# define GL_VERSION_2_0_DEPRECATED +# define GL_VERSION_2_1_DEPRECATED +// ignore everything above 2.1 +# define GL_VERSION_3_0 +# define GL_VERSION_3_0_DEPRECATED +# define GL_VERSION_3_1 +# define GL_VERSION_3_2 +# define GL_VERSION_3_3 +# define GL_VERSION_4_0 +# define GL_VERSION_4_1 +# define GL_VERSION_4_2 +# include +#elif BGFX_CONFIG_RENDERER_OPENGLES2 +# include +# include + +# if BX_PLATFORM_WINDOWS +# include +# undef BGFX_USE_EGL +# define BGFX_USE_EGL 1 +# endif // BX_PLATFORM_ + +# 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_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE +# define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 +# endif // GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE + +typedef void (*PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); + +#endif // BGFX_CONFIG_RENDERER_OPENGL + +#if BX_PLATFORM_NACL +# include +# include +# include +# include +#elif BX_PLATFORM_WINDOWS +# include +#elif BX_PLATFORM_LINUX +# include +#endif // BX_PLATFORM_ + +#if BGFX_CONFIG_DEBUG_GREMEDY && (BX_PLATFORM_WINDOWS || BX_PLATFORM_LINUX) +# include +#endif // BGFX_CONFIG_DEBUG_GREMEDY && (BX_PLATFORM_WINDOWS || BX_PLATFORM_LINUX) + +#if BGFX_USE_WGL +typedef PROC (APIENTRYP PFNWGLGETPROCADDRESSPROC) (LPCSTR lpszProc); +typedef BOOL (APIENTRYP PFNWGLMAKECURRENTPROC) (HDC hdc, HGLRC hglrc); +typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTPROC) (HDC hdc); +typedef BOOL (APIENTRYP PFNWGLDELETECONTEXTPROC) (HGLRC hglrc); +// +typedef GLenum (APIENTRYP PFNGLGETERRORPROC) (void); +typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); +typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); +typedef void (APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); +typedef void (APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); +typedef void (APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func); +typedef void (APIENTRYP PFNGLDISABLEPROC) (GLenum cap); +typedef void (APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); +typedef void (APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *params); +typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); +typedef void (APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); +typedef void (APIENTRYP PFNGLPOINTSIZEPROC) (GLfloat size); +typedef void (APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); +typedef void (APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLENABLEPROC) (GLenum cap); +typedef void (APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s); +typedef void (APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag); +typedef void (APIENTRYP PFNGLCLEARDEPTHPROC) (GLdouble depth); +typedef void (APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +#endif // BGFX_USE_WGL + +#ifndef GL_APIENTRY +# define GL_APIENTRY APIENTRY +#endif // GL_APIENTRY + +#ifndef GL_APIENTRYP +# define GL_APIENTRYP APIENTRYP +#endif // GL_APIENTRYP + +namespace bgfx +{ typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORBGFXPROC)(GLuint _index, GLuint _divisor); typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDBGFXPROC)(GLenum _mode, GLint _first, GLsizei _count, GLsizei _primcount); - typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBGFXPROC)(GLenum _mode, GLsizei _count, GLenum _type, const GLvoid* _indices, GLsizei _primcount); - -# 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 - -#if BGFX_CONFIG_DEBUG_GREMEDY -# define _GREMEDY_SETMARKER(_string) \ - do \ - { \ - if (NULL != glStringMarkerGREMEDY) \ - { \ - glStringMarkerGREMEDY( (GLsizei)strlen(_string), _string); \ - } \ - } while(0) -# define _GREMEDY_FRAMETERMINATOR() \ - do \ - { \ - if (NULL != glStringMarkerGREMEDY) \ - { \ - glFrameTerminatorGREMEDY(); \ - } \ - } while(0) -#else -# define _GREMEDY_SETMARKER(_string) do {} while(0) -# define _GREMEDY_FRAMETERMINATOR() do {} while(0) -#endif // BGFX_CONFIG_DEBUG_GREMEDY - -#define GREMEDY_SETMARKER(_string) _GREMEDY_SETMARKER(_string) -#define GREMEDY_FRAMETERMINATOR() _GREMEDY_FRAMETERMINATOR() - -#if BGFX_USE_WGL - extern PFNWGLGETPROCADDRESSPROC wglGetProcAddress; - extern PFNWGLMAKECURRENTPROC wglMakeCurrent; - extern PFNWGLCREATECONTEXTPROC wglCreateContext; -#endif // BGFX_USE_WGL - -#define GL_IMPORT(_optional, _proto, _func) extern _proto _func -#include "glimports.h" -#undef GL_IMPORT - - 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 _offset, uint32_t _size, void* _data) - { - 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() - { - 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 _offset, uint32_t _size, void* _data) - { - 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() - { - 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, GLenum _min, GLenum _mag); - 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) - { - m_hash = hash(_code, (uint32_t)strlen( (const char*)_code) ); - 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; - uint32_t m_hash; - }; - - struct RenderTarget - { - void create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags); - 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); - void destroy(); - void init(); - void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const; - void bindInstanceData(uint32_t _stride, uint32_t _baseVertex = 0) const; - - GLuint m_id; - - uint8_t m_used[Attrib::Count+1]; // dense - uint16_t m_attributes[Attrib::Count]; // sparse - uint16_t m_instanceData[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT]; - 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; - }; - -#if BGFX_CONFIG_RENDERER_OPENGL - struct Queries - { - void create() - { - glGenQueries(countof(m_queries), m_queries); - } - - void destroy() - { - glDeleteQueries(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]; - }; -#endif // BGFX_CONFIG_RENDERER_OPENGL - -} // namespace bgfx - -#endif // __RENDERER_GL_H__ + typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBGFXPROC)(GLenum _mode, GLsizei _count, GLenum _type, const GLvoid* _indices, GLsizei _primcount); + +# 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 + +#if BGFX_CONFIG_DEBUG_GREMEDY +# define _GREMEDY_SETMARKER(_string) \ + do \ + { \ + if (NULL != glStringMarkerGREMEDY) \ + { \ + glStringMarkerGREMEDY( (GLsizei)strlen(_string), _string); \ + } \ + } while(0) +# define _GREMEDY_FRAMETERMINATOR() \ + do \ + { \ + if (NULL != glStringMarkerGREMEDY) \ + { \ + glFrameTerminatorGREMEDY(); \ + } \ + } while(0) +#else +# define _GREMEDY_SETMARKER(_string) do {} while(0) +# define _GREMEDY_FRAMETERMINATOR() do {} while(0) +#endif // BGFX_CONFIG_DEBUG_GREMEDY + +#define GREMEDY_SETMARKER(_string) _GREMEDY_SETMARKER(_string) +#define GREMEDY_FRAMETERMINATOR() _GREMEDY_FRAMETERMINATOR() + +#if BGFX_USE_WGL + extern PFNWGLGETPROCADDRESSPROC wglGetProcAddress; + extern PFNWGLMAKECURRENTPROC wglMakeCurrent; + extern PFNWGLCREATECONTEXTPROC wglCreateContext; +#endif // BGFX_USE_WGL + +#define GL_IMPORT(_optional, _proto, _func) extern _proto _func +#include "glimports.h" +#undef GL_IMPORT + + 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 _offset, uint32_t _size, void* _data) + { + 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() + { + 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 _offset, uint32_t _size, void* _data) + { + 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() + { + 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, GLenum _min, GLenum _mag); + 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) + { + m_hash = hash(_code, (uint32_t)strlen( (const char*)_code) ); + 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; + uint32_t m_hash; + }; + + struct RenderTarget + { + void create(uint16_t _width, uint16_t _height, uint32_t _flags, uint32_t _textureFlags); + 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); + void destroy(); + void init(); + void bindAttributes(const VertexDecl& _vertexDecl, uint32_t _baseVertex = 0) const; + void bindInstanceData(uint32_t _stride, uint32_t _baseVertex = 0) const; + + GLuint m_id; + + uint8_t m_used[Attrib::Count+1]; // dense + uint16_t m_attributes[Attrib::Count]; // sparse + uint16_t m_instanceData[BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT]; + 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; + }; + +#if BGFX_CONFIG_RENDERER_OPENGL + struct Queries + { + void create() + { + glGenQueries(countof(m_queries), m_queries); + } + + void destroy() + { + glDeleteQueries(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]; + }; +#endif // BGFX_CONFIG_RENDERER_OPENGL + +} // namespace bgfx + +#endif // __RENDERER_GL_H__