2012-07-08 19:10:07 -07:00
/*
2016-01-01 00:11:04 -08:00
* Copyright 2011 - 2016 Branimir Karadzic . All rights reserved .
* License : https : //github.com/bkaradzic/bgfx#license-bsd-2-clause
2012-07-08 19:10:07 -07:00
*/
# include "bgfx_p.h"
2014-08-21 22:05:02 -07:00
# if (BGFX_CONFIG_RENDERER_OPENGLES || BGFX_CONFIG_RENDERER_OPENGL)
2012-07-08 19:10:07 -07:00
# include "renderer_gl.h"
# include <bx / timer.h>
# include <bx / uint32_t.h>
2015-11-16 10:42:56 -04:00
# if BGFX_CONFIG_PROFILER_REMOTERY
# define BGFX_GPU_PROFILER_BIND() rmt_BindOpenGL()
# define BGFX_GPU_PROFILER_UNBIND() rmt_UnbindOpenGL()
# define BGFX_GPU_PROFILER_BEGIN(_group, _name, _color) rmt_BeginOpenGLSample(_group##_##_name)
# define BGFX_GPU_PROFILER_BEGIN_DYNAMIC(_namestr) rmt_BeginOpenGLSampleDynamic(_namestr)
# define BGFX_GPU_PROFILER_END() rmt_EndOpenGLSample()
# else
2015-11-16 08:45:13 -08:00
# define BGFX_GPU_PROFILER_BIND() BX_NOOP()
2015-11-16 10:42:56 -04:00
# define BGFX_GPU_PROFILER_UNBIND() BX_NOOP()
# define BGFX_GPU_PROFILER_BEGIN(_group, _name, _color) BX_NOOP()
# define BGFX_GPU_PROFILER_BEGIN_DYNAMIC(_namestr) BX_NOOP()
# define BGFX_GPU_PROFILER_END() BX_NOOP()
2015-11-16 08:45:13 -08:00
# endif // BGFX_CONFIG_PROFILER_REMOTERY
2015-11-16 10:42:56 -04:00
2015-03-21 22:11:59 -07:00
namespace bgfx { namespace gl
2012-07-08 19:10:07 -07:00
{
2014-10-25 18:07:51 -07:00
static char s_viewName [ BGFX_CONFIG_MAX_VIEWS ] [ BGFX_CONFIG_MAX_VIEW_NAME ] ;
2013-06-09 15:28:25 -07:00
2014-04-26 23:48:41 -07:00
struct PrimInfo
2013-07-24 21:59:59 -07:00
{
2014-04-26 23:48:41 -07:00
GLenum m_type ;
uint32_t m_min ;
uint32_t m_div ;
uint32_t m_sub ;
} ;
static const PrimInfo s_primInfo [ ] =
{
{ GL_TRIANGLES , 3 , 3 , 0 } ,
{ GL_TRIANGLE_STRIP , 3 , 1 , 2 } ,
{ GL_LINES , 2 , 2 , 0 } ,
2014-10-22 19:19:33 -07:00
{ GL_LINE_STRIP , 2 , 1 , 1 } ,
2014-04-26 23:48:41 -07:00
{ GL_POINTS , 1 , 1 , 0 } ,
} ;
static const char * s_primName [ ] =
{
" TriList " ,
" TriStrip " ,
" Line " ,
2014-10-22 19:19:33 -07:00
" LineStrip " ,
2014-04-26 23:48:41 -07:00
" Point " ,
2013-07-24 21:59:59 -07:00
} ;
2014-08-04 22:01:20 -07:00
static const char * s_attribName [ ] =
2013-07-24 21:59:59 -07:00
{
" a_position " ,
" a_normal " ,
" a_tangent " ,
2014-08-17 17:20:15 -07:00
" a_bitangent " ,
2013-07-24 21:59:59 -07:00
" a_color0 " ,
" a_color1 " ,
" a_indices " ,
" a_weight " ,
" a_texcoord0 " ,
" a_texcoord1 " ,
" a_texcoord2 " ,
" a_texcoord3 " ,
" a_texcoord4 " ,
" a_texcoord5 " ,
" a_texcoord6 " ,
" a_texcoord7 " ,
} ;
2014-08-04 22:01:20 -07:00
BX_STATIC_ASSERT ( Attrib : : Count = = BX_COUNTOF ( s_attribName ) ) ;
2013-07-24 21:59:59 -07:00
2014-10-05 00:14:21 -07:00
static const char * s_instanceDataName [ ] =
2013-07-24 21:59:59 -07:00
{
" i_data0 " ,
" i_data1 " ,
" i_data2 " ,
" i_data3 " ,
" i_data4 " ,
} ;
2014-10-05 00:14:21 -07:00
BX_STATIC_ASSERT ( BGFX_CONFIG_MAX_INSTANCE_DATA_COUNT = = BX_COUNTOF ( s_instanceDataName ) ) ;
2013-07-24 21:59:59 -07:00
2014-10-05 00:14:21 -07:00
static const GLenum s_access [ ] =
2014-07-20 20:27:13 -07:00
{
GL_READ_ONLY ,
GL_WRITE_ONLY ,
GL_READ_WRITE ,
} ;
2014-10-05 00:14:21 -07:00
BX_STATIC_ASSERT ( Access : : Count = = BX_COUNTOF ( s_access ) ) ;
2014-07-20 20:27:13 -07:00
2014-10-05 00:14:21 -07:00
static const GLenum s_attribType [ ] =
2013-07-24 21:59:59 -07:00
{
2015-08-04 19:03:56 -07:00
GL_UNSIGNED_BYTE , // Uint8
GL_UNSIGNED_INT_10_10_10_2 , // Uint10
GL_SHORT , // Int16
GL_HALF_FLOAT , // Half
GL_FLOAT , // Float
2013-07-24 21:59:59 -07:00
} ;
2014-10-05 00:14:21 -07:00
BX_STATIC_ASSERT ( AttribType : : Count = = BX_COUNTOF ( s_attribType ) ) ;
2013-07-24 21:59:59 -07:00
struct Blend
{
GLenum m_src ;
GLenum m_dst ;
bool m_factor ;
} ;
static const Blend s_blendFactor [ ] =
{
{ 0 , 0 , false } , // ignored
2014-03-25 23:07:51 -07:00
{ GL_ZERO , GL_ZERO , false } , // ZERO
{ GL_ONE , GL_ONE , false } , // ONE
{ GL_SRC_COLOR , GL_SRC_COLOR , false } , // SRC_COLOR
{ GL_ONE_MINUS_SRC_COLOR , GL_ONE_MINUS_SRC_COLOR , false } , // INV_SRC_COLOR
{ GL_SRC_ALPHA , GL_SRC_ALPHA , false } , // SRC_ALPHA
{ GL_ONE_MINUS_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA , false } , // INV_SRC_ALPHA
{ GL_DST_ALPHA , GL_DST_ALPHA , false } , // DST_ALPHA
{ GL_ONE_MINUS_DST_ALPHA , GL_ONE_MINUS_DST_ALPHA , false } , // INV_DST_ALPHA
{ GL_DST_COLOR , GL_DST_COLOR , false } , // DST_COLOR
{ GL_ONE_MINUS_DST_COLOR , GL_ONE_MINUS_DST_COLOR , false } , // INV_DST_COLOR
{ GL_SRC_ALPHA_SATURATE , GL_ONE , false } , // SRC_ALPHA_SAT
{ GL_CONSTANT_COLOR , GL_CONSTANT_COLOR , true } , // FACTOR
{ GL_ONE_MINUS_CONSTANT_COLOR , GL_ONE_MINUS_CONSTANT_COLOR , true } , // INV_FACTOR
2013-07-24 21:59:59 -07:00
} ;
static const GLenum s_blendEquation [ ] =
{
GL_FUNC_ADD ,
GL_FUNC_SUBTRACT ,
GL_FUNC_REVERSE_SUBTRACT ,
GL_MIN ,
GL_MAX ,
} ;
2014-02-23 11:21:23 -08:00
static const GLenum s_cmpFunc [ ] =
2013-07-24 21:59:59 -07:00
{
0 , // ignored
GL_LESS ,
GL_LEQUAL ,
GL_EQUAL ,
GL_GEQUAL ,
GL_GREATER ,
GL_NOTEQUAL ,
GL_NEVER ,
GL_ALWAYS ,
} ;
static const GLenum s_stencilOp [ ] =
{
GL_ZERO ,
GL_KEEP ,
GL_REPLACE ,
GL_INCR_WRAP ,
GL_INCR ,
GL_DECR_WRAP ,
GL_DECR ,
GL_INVERT ,
} ;
static const GLenum s_stencilFace [ ] =
{
GL_FRONT_AND_BACK ,
GL_FRONT ,
GL_BACK ,
} ;
2015-09-11 20:05:13 -07:00
static GLenum s_textureAddress [ ] =
2013-07-24 21:59:59 -07:00
{
GL_REPEAT ,
GL_MIRRORED_REPEAT ,
GL_CLAMP_TO_EDGE ,
2015-09-11 20:05:13 -07:00
GL_CLAMP_TO_BORDER ,
2013-07-24 21:59:59 -07:00
} ;
static const GLenum s_textureFilterMag [ ] =
{
GL_LINEAR ,
GL_NEAREST ,
GL_LINEAR ,
} ;
static const GLenum s_textureFilterMin [ ] [ 3 ] =
{
2016-03-23 00:17:15 +01:00
{ GL_LINEAR , GL_LINEAR_MIPMAP_LINEAR , GL_LINEAR_MIPMAP_NEAREST } ,
{ GL_NEAREST , GL_NEAREST_MIPMAP_LINEAR , GL_NEAREST_MIPMAP_NEAREST } ,
{ GL_LINEAR , GL_LINEAR_MIPMAP_LINEAR , GL_LINEAR_MIPMAP_NEAREST } ,
2013-07-24 21:59:59 -07:00
} ;
struct TextureFormatInfo
{
GLenum m_internalFmt ;
2015-05-04 20:57:22 -07:00
GLenum m_internalFmtSrgb ;
2013-07-24 21:59:59 -07:00
GLenum m_fmt ;
GLenum m_type ;
bool m_supported ;
} ;
2014-07-20 20:27:13 -07:00
static TextureFormatInfo s_textureFormat [ ] =
2013-07-24 21:59:59 -07:00
{
2015-05-04 20:57:22 -07:00
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT , GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT , GL_COMPRESSED_RGBA_S3TC_DXT1_EXT , GL_ZERO , false } , // BC1
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT , GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT , GL_COMPRESSED_RGBA_S3TC_DXT3_EXT , GL_ZERO , false } , // BC2
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT , GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , GL_ZERO , false } , // BC3
{ GL_COMPRESSED_LUMINANCE_LATC1_EXT , GL_ZERO , GL_COMPRESSED_LUMINANCE_LATC1_EXT , GL_ZERO , false } , // BC4
{ GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT , GL_ZERO , GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT , GL_ZERO , false } , // BC5
{ GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB , GL_ZERO , GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB , GL_ZERO , false } , // BC6H
{ GL_COMPRESSED_RGBA_BPTC_UNORM_ARB , GL_ZERO , GL_COMPRESSED_RGBA_BPTC_UNORM_ARB , GL_ZERO , false } , // BC7
{ GL_ETC1_RGB8_OES , GL_ZERO , GL_ETC1_RGB8_OES , GL_ZERO , false } , // ETC1
{ GL_COMPRESSED_RGB8_ETC2 , GL_ZERO , GL_COMPRESSED_RGB8_ETC2 , GL_ZERO , false } , // ETC2
{ GL_COMPRESSED_RGBA8_ETC2_EAC , GL_COMPRESSED_SRGB8_ETC2 , GL_COMPRESSED_RGBA8_ETC2_EAC , GL_ZERO , false } , // ETC2A
{ GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_ZERO , false } , // ETC2A1
{ GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG , GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT , GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG , GL_ZERO , false } , // PTC12
{ GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG , GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT , GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG , GL_ZERO , false } , // PTC14
{ GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG , GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT , GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG , GL_ZERO , false } , // PTC12A
{ GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG , GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT , GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG , GL_ZERO , false } , // PTC14A
{ GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG , GL_ZERO , GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG , GL_ZERO , false } , // PTC22
{ GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG , GL_ZERO , GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG , GL_ZERO , false } , // PTC24
{ GL_ZERO , GL_ZERO , GL_ZERO , GL_ZERO , false } , // Unknown
{ GL_ZERO , GL_ZERO , GL_ZERO , GL_ZERO , false } , // R1
2015-08-31 10:16:36 -07:00
{ GL_ALPHA , GL_ZERO , GL_ALPHA , GL_UNSIGNED_BYTE , false } , // A8
2015-05-04 20:57:22 -07:00
{ GL_R8 , GL_ZERO , GL_RED , GL_UNSIGNED_BYTE , false } , // R8
2015-08-28 17:41:24 -07:00
{ GL_R8I , GL_ZERO , GL_RED , GL_BYTE , false } , // R8S
{ GL_R8UI , GL_ZERO , GL_RED , GL_UNSIGNED_BYTE , false } , // R8S
2015-08-27 16:35:27 -07:00
{ GL_R8_SNORM , GL_ZERO , GL_RED , GL_BYTE , false } , // R8S
2015-08-28 17:41:24 -07:00
{ GL_R16 , GL_ZERO , GL_RED , GL_UNSIGNED_SHORT , false } , // R16
{ GL_R16I , GL_ZERO , GL_RED , GL_SHORT , false } , // R16I
{ GL_R16UI , GL_ZERO , GL_RED , GL_UNSIGNED_SHORT , false } , // R16U
2015-05-04 20:57:22 -07:00
{ GL_R16F , GL_ZERO , GL_RED , GL_HALF_FLOAT , false } , // R16F
2015-08-27 16:35:27 -07:00
{ GL_R16_SNORM , GL_ZERO , GL_RED , GL_SHORT , false } , // R16S
2015-08-31 10:16:36 -07:00
{ GL_R32I , GL_ZERO , GL_RED , GL_INT , false } , // R32I
2015-08-28 14:48:51 -07:00
{ GL_R32UI , GL_ZERO , GL_RED , GL_UNSIGNED_INT , false } , // R32U
2015-05-04 20:57:22 -07:00
{ GL_R32F , GL_ZERO , GL_RED , GL_FLOAT , false } , // R32F
{ GL_RG8 , GL_ZERO , GL_RG , GL_UNSIGNED_BYTE , false } , // RG8
2015-08-28 17:41:24 -07:00
{ GL_RG8I , GL_ZERO , GL_RG , GL_BYTE , false } , // RG8I
{ GL_RG8UI , GL_ZERO , GL_RG , GL_UNSIGNED_BYTE , false } , // RG8U
2015-08-27 16:35:27 -07:00
{ GL_RG8_SNORM , GL_ZERO , GL_RG , GL_BYTE , false } , // RG8S
2015-05-04 20:57:22 -07:00
{ GL_RG16 , GL_ZERO , GL_RG , GL_UNSIGNED_SHORT , false } , // RG16
2015-08-28 17:41:24 -07:00
{ GL_RG16I , GL_ZERO , GL_RG , GL_SHORT , false } , // RG16
{ GL_RG16UI , GL_ZERO , GL_RG , GL_UNSIGNED_SHORT , false } , // RG16
2015-05-04 20:57:22 -07:00
{ GL_RG16F , GL_ZERO , GL_RG , GL_FLOAT , false } , // RG16F
2015-08-27 16:35:27 -07:00
{ GL_RG16_SNORM , GL_ZERO , GL_RG , GL_SHORT , false } , // RG16S
2015-08-31 10:16:36 -07:00
{ GL_RG32I , GL_ZERO , GL_RG , GL_INT , false } , // RG32I
2015-08-28 14:48:51 -07:00
{ GL_RG32UI , GL_ZERO , GL_RG , GL_UNSIGNED_INT , false } , // RG32U
2015-05-04 20:57:22 -07:00
{ GL_RG32F , GL_ZERO , GL_RG , GL_FLOAT , false } , // RG32F
2016-02-24 15:57:58 -08:00
{ GL_RGB8 , GL_SRGB8 , GL_RGB , GL_UNSIGNED_BYTE , false } , // RGB8
{ GL_RGB8I , GL_ZERO , GL_RGB , GL_BYTE , false } , // RGB8I
{ GL_RGB8UI , GL_ZERO , GL_RGB , GL_UNSIGNED_BYTE , false } , // RGB8U
{ GL_RGB8_SNORM , GL_ZERO , GL_RGB , GL_BYTE , false } , // RGB8S
2015-09-29 16:06:06 -07:00
{ GL_RGB9_E5 , GL_ZERO , GL_RGB , GL_UNSIGNED_INT_5_9_9_9_REV , false } , // RGB9E5F
2015-05-04 20:57:22 -07:00
{ GL_RGBA8 , GL_SRGB8_ALPHA8 , GL_BGRA , GL_UNSIGNED_BYTE , false } , // BGRA8
{ GL_RGBA8 , GL_SRGB8_ALPHA8 , GL_RGBA , GL_UNSIGNED_BYTE , false } , // RGBA8
2015-08-28 17:41:24 -07:00
{ GL_RGBA8I , GL_ZERO , GL_RGBA , GL_BYTE , false } , // RGBA8I
{ GL_RGBA8UI , GL_ZERO , GL_RGBA , GL_UNSIGNED_BYTE , false } , // RGBA8U
2015-08-27 16:35:27 -07:00
{ GL_RGBA8_SNORM , GL_ZERO , GL_RGBA , GL_BYTE , false } , // RGBA8S
{ GL_RGBA16 , GL_ZERO , GL_RGBA , GL_UNSIGNED_SHORT , false } , // RGBA16
2015-08-28 17:41:24 -07:00
{ GL_RGBA16I , GL_ZERO , GL_RGBA , GL_SHORT , false } , // RGBA16I
{ GL_RGBA16UI , GL_ZERO , GL_RGBA , GL_UNSIGNED_SHORT , false } , // RGBA16U
2015-05-04 20:57:22 -07:00
{ GL_RGBA16F , GL_ZERO , GL_RGBA , GL_HALF_FLOAT , false } , // RGBA16F
2015-08-27 16:35:27 -07:00
{ GL_RGBA16_SNORM , GL_ZERO , GL_RGBA , GL_SHORT , false } , // RGBA16S
2015-08-31 10:16:36 -07:00
{ GL_RGBA32I , GL_ZERO , GL_RGBA , GL_INT , false } , // RGBA32I
2015-08-28 14:48:51 -07:00
{ GL_RGBA32UI , GL_ZERO , GL_RGBA , GL_UNSIGNED_INT , false } , // RGBA32U
2015-05-04 20:57:22 -07:00
{ GL_RGBA32F , GL_ZERO , GL_RGBA , GL_FLOAT , false } , // RGBA32F
2016-02-22 17:32:20 -08:00
{ GL_RGB565 , GL_ZERO , GL_RGB , GL_UNSIGNED_SHORT_5_6_5 , false } , // R5G6B5
2016-01-11 14:49:56 -08:00
{ GL_RGBA4 , GL_ZERO , GL_RGBA , GL_UNSIGNED_SHORT_4_4_4_4_REV , false } , // RGBA4
{ GL_RGB5_A1 , GL_ZERO , GL_RGBA , GL_UNSIGNED_SHORT_1_5_5_5_REV , false } , // RGB5A1
2015-05-04 20:57:22 -07:00
{ GL_RGB10_A2 , GL_ZERO , GL_RGBA , GL_UNSIGNED_INT_2_10_10_10_REV , false } , // RGB10A2
{ GL_R11F_G11F_B10F , GL_ZERO , GL_RGB , GL_UNSIGNED_INT_10F_11F_11F_REV , false } , // R11G11B10F
{ GL_ZERO , GL_ZERO , GL_ZERO , GL_ZERO , false } , // UnknownDepth
{ GL_DEPTH_COMPONENT16 , GL_ZERO , GL_DEPTH_COMPONENT , GL_UNSIGNED_SHORT , false } , // D16
{ GL_DEPTH_COMPONENT24 , GL_ZERO , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , false } , // D24
{ GL_DEPTH24_STENCIL8 , GL_ZERO , GL_DEPTH_STENCIL , GL_UNSIGNED_INT_24_8 , false } , // D24S8
{ GL_DEPTH_COMPONENT32 , GL_ZERO , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , false } , // D32
{ GL_DEPTH_COMPONENT32F , GL_ZERO , GL_DEPTH_COMPONENT , GL_FLOAT , false } , // D16F
{ GL_DEPTH_COMPONENT32F , GL_ZERO , GL_DEPTH_COMPONENT , GL_FLOAT , false } , // D24F
{ GL_DEPTH_COMPONENT32F , GL_ZERO , GL_DEPTH_COMPONENT , GL_FLOAT , false } , // D32F
{ GL_STENCIL_INDEX8 , GL_ZERO , GL_STENCIL_INDEX , GL_UNSIGNED_BYTE , false } , // D0S8
2013-07-24 21:59:59 -07:00
} ;
2014-07-20 20:27:13 -07:00
BX_STATIC_ASSERT ( TextureFormat : : Count = = BX_COUNTOF ( s_textureFormat ) ) ;
2015-03-28 21:25:40 -07:00
static bool s_textureFilter [ TextureFormat : : Count + 1 ] ;
2015-03-01 12:33:27 -08:00
static GLenum s_rboFormat [ ] =
{
GL_ZERO , // BC1
GL_ZERO , // BC2
GL_ZERO , // BC3
GL_ZERO , // BC4
GL_ZERO , // BC5
GL_ZERO , // BC6H
GL_ZERO , // BC7
GL_ZERO , // ETC1
GL_ZERO , // ETC2
GL_ZERO , // ETC2A
GL_ZERO , // ETC2A1
GL_ZERO , // PTC12
GL_ZERO , // PTC14
GL_ZERO , // PTC12A
GL_ZERO , // PTC14A
GL_ZERO , // PTC22
GL_ZERO , // PTC24
GL_ZERO , // Unknown
GL_ZERO , // R1
2015-08-31 10:16:36 -07:00
GL_ALPHA , // A8
2015-03-01 12:33:27 -08:00
GL_R8 , // R8
2015-08-28 17:41:24 -07:00
GL_R8I , // R8I
GL_R8UI , // R8U
2015-08-27 16:35:27 -07:00
GL_R8_SNORM , // R8S
2015-08-28 17:41:24 -07:00
GL_R16 , // R16
GL_R16I , // R16I
GL_R16UI , // R16U
2015-03-01 12:33:27 -08:00
GL_R16F , // R16F
2015-08-27 16:35:27 -07:00
GL_R16_SNORM , // R16S
2015-08-31 10:16:36 -07:00
GL_R32I , // R32I
2015-08-28 14:48:51 -07:00
GL_R32UI , // R32U
2015-03-01 12:33:27 -08:00
GL_R32F , // R32F
GL_RG8 , // RG8
2015-08-28 17:41:24 -07:00
GL_RG8I , // RG8I
GL_RG8UI , // RG8U
2015-08-27 16:35:27 -07:00
GL_RG8_SNORM , // RG8S
2015-03-01 12:33:27 -08:00
GL_RG16 , // RG16
2015-08-28 17:41:24 -07:00
GL_RG16I , // RG16I
GL_RG16UI , // RG16U
2015-03-01 12:33:27 -08:00
GL_RG16F , // RG16F
2015-08-27 16:35:27 -07:00
GL_RG16_SNORM , // RG16S
2015-08-31 10:16:36 -07:00
GL_RG32I , // RG32I
2015-08-28 14:48:51 -07:00
GL_RG32UI , // RG32U
2015-03-01 12:33:27 -08:00
GL_RG32F , // RG32F
2016-02-24 15:51:51 -08:00
GL_RGB8 , // RGB8
GL_RGB8I , // RGB8I
GL_RGB8UI , // RGB8UI
GL_RGB8_SNORM , // RGB8S
2015-09-29 16:06:06 -07:00
GL_RGB9_E5 , // RGB9E5F
2015-03-01 12:33:27 -08:00
GL_RGBA8 , // BGRA8
2015-03-05 17:44:56 -08:00
GL_RGBA8 , // RGBA8
2015-08-28 17:41:24 -07:00
GL_RGBA8I , // RGBA8I
GL_RGBA8UI , // RGBA8UI
2015-08-27 16:35:27 -07:00
GL_RGBA8_SNORM , // RGBA8S
2015-03-01 12:33:27 -08:00
GL_RGBA16 , // RGBA16
2015-08-28 17:41:24 -07:00
GL_RGBA16I , // RGBA16I
GL_RGBA16UI , // RGBA16U
2015-03-01 12:33:27 -08:00
GL_RGBA16F , // RGBA16F
2015-08-27 16:35:27 -07:00
GL_RGBA16_SNORM , // RGBA16S
2015-08-31 10:16:36 -07:00
GL_RGBA32I , // RGBA32I
2015-08-28 14:48:51 -07:00
GL_RGBA32UI , // RGBA32U
2015-03-01 12:33:27 -08:00
GL_RGBA32F , // RGBA32F
GL_RGB565 , // R5G6B5
GL_RGBA4 , // RGBA4
GL_RGB5_A1 , // RGB5A1
GL_RGB10_A2 , // RGB10A2
GL_R11F_G11F_B10F , // R11G11B10F
GL_ZERO , // UnknownDepth
GL_DEPTH_COMPONENT16 , // D16
GL_DEPTH_COMPONENT24 , // D24
GL_DEPTH24_STENCIL8 , // D24S8
GL_DEPTH_COMPONENT32 , // D32
GL_DEPTH_COMPONENT32F , // D16F
GL_DEPTH_COMPONENT32F , // D24F
GL_DEPTH_COMPONENT32F , // D32F
GL_STENCIL_INDEX8 , // D0S8
} ;
BX_STATIC_ASSERT ( TextureFormat : : Count = = BX_COUNTOF ( s_rboFormat ) ) ;
2014-07-20 20:27:13 -07:00
static GLenum s_imageFormat [ ] =
{
2014-08-26 20:56:53 -07:00
GL_ZERO , // BC1
GL_ZERO , // BC2
GL_ZERO , // BC3
GL_ZERO , // BC4
GL_ZERO , // BC5
GL_ZERO , // BC6H
GL_ZERO , // BC7
GL_ZERO , // ETC1
GL_ZERO , // ETC2
GL_ZERO , // ETC2A
GL_ZERO , // ETC2A1
GL_ZERO , // PTC12
GL_ZERO , // PTC14
GL_ZERO , // PTC12A
GL_ZERO , // PTC14A
GL_ZERO , // PTC22
GL_ZERO , // PTC24
GL_ZERO , // Unknown
GL_ZERO , // R1
2015-08-31 10:16:36 -07:00
GL_ALPHA , // A8
2014-08-26 20:56:53 -07:00
GL_R8 , // R8
2015-08-28 17:41:24 -07:00
GL_R8I , // R8I
GL_R8UI , // R8UI
2015-08-27 16:35:27 -07:00
GL_R8_SNORM , // R8S
2015-08-28 17:41:24 -07:00
GL_R16 , // R16
GL_R16I , // R16I
GL_R16UI , // R16U
2014-08-26 20:56:53 -07:00
GL_R16F , // R16F
2015-08-27 16:35:27 -07:00
GL_R16_SNORM , // R16S
2015-08-31 10:16:36 -07:00
GL_R32I , // R32I
2015-08-28 14:48:51 -07:00
GL_R32UI , // R32U
2014-08-26 20:56:53 -07:00
GL_R32F , // R32F
GL_RG8 , // RG8
2015-08-28 17:41:24 -07:00
GL_RG8I , // RG8I
GL_RG8UI , // RG8U
2015-08-27 16:35:27 -07:00
GL_RG8_SNORM , // RG8S
2014-08-26 20:56:53 -07:00
GL_RG16 , // RG16
2015-08-28 17:41:24 -07:00
GL_RG16I , // RG16I
GL_RG16UI , // RG16U
2014-08-26 20:56:53 -07:00
GL_RG16F , // RG16F
2015-08-27 16:35:27 -07:00
GL_RG16_SNORM , // RG16S
2015-08-31 10:16:36 -07:00
GL_RG32I , // RG32I
2015-08-28 14:48:51 -07:00
GL_RG32UI , // RG32U
2014-08-26 20:56:53 -07:00
GL_RG32F , // RG32F
2016-02-24 15:51:51 -08:00
GL_RGB8 , // RGB8
GL_RGB8I , // RGB8I
GL_RGB8UI , // RGB8UI
GL_RGB8_SNORM , // RGB8S
2015-09-29 16:06:06 -07:00
GL_RGB9_E5 , // RGB9E5F
2014-08-26 20:56:53 -07:00
GL_RGBA8 , // BGRA8
2015-03-05 17:44:56 -08:00
GL_RGBA8 , // RGBA8
2015-08-28 17:41:24 -07:00
GL_RGBA8I , // RGBA8I
GL_RGBA8UI , // RGBA8UI
2015-08-27 16:35:27 -07:00
GL_RGBA8_SNORM , // RGBA8S
2014-08-26 20:56:53 -07:00
GL_RGBA16 , // RGBA16
2015-08-28 17:41:24 -07:00
GL_RGBA16I , // RGBA16I
GL_RGBA16UI , // RGBA16U
2014-08-26 20:56:53 -07:00
GL_RGBA16F , // RGBA16F
2015-08-27 16:35:27 -07:00
GL_RGBA16_SNORM , // RGBA16S
2015-08-31 10:16:36 -07:00
GL_RGBA32I , // RGBA32I
2015-08-28 14:48:51 -07:00
GL_RGBA32UI , // RGBA32U
2014-08-26 20:56:53 -07:00
GL_RGBA32F , // RGBA32F
GL_RGB565 , // R5G6B5
GL_RGBA4 , // RGBA4
GL_RGB5_A1 , // RGB5A1
GL_RGB10_A2 , // RGB10A2
GL_R11F_G11F_B10F , // R11G11B10F
GL_ZERO , // UnknownDepth
GL_ZERO , // D16
GL_ZERO , // D24
GL_ZERO , // D24S8
GL_ZERO , // D32
GL_ZERO , // D16F
GL_ZERO , // D24F
GL_ZERO , // D32F
GL_ZERO , // D0S8
2014-07-20 20:27:13 -07:00
} ;
BX_STATIC_ASSERT ( TextureFormat : : Count = = BX_COUNTOF ( s_imageFormat ) ) ;
2013-07-24 21:59:59 -07:00
2012-12-30 20:52:47 -08:00
struct Extension
{
enum Enum
{
2014-08-26 20:56:53 -07:00
AMD_conservative_depth ,
2015-04-29 23:20:21 -07:00
AMD_multi_draw_indirect ,
2014-08-26 20:56:53 -07:00
2014-02-19 23:49:28 -08:00
ANGLE_depth_texture ,
ANGLE_framebuffer_blit ,
ANGLE_framebuffer_multisample ,
2013-07-21 19:27:47 -07:00
ANGLE_instanced_arrays ,
2014-02-19 23:49:28 -08:00
ANGLE_texture_compression_dxt1 ,
ANGLE_texture_compression_dxt3 ,
ANGLE_texture_compression_dxt5 ,
2015-03-30 00:06:34 -07:00
ANGLE_timer_query ,
2013-07-21 19:27:47 -07:00
ANGLE_translated_shader_source ,
2014-02-19 23:49:28 -08:00
2013-09-03 20:13:07 -07:00
APPLE_texture_format_BGRA8888 ,
2014-03-09 21:20:34 -07:00
APPLE_texture_max_level ,
2014-02-19 23:49:28 -08:00
2014-07-20 20:27:13 -07:00
ARB_compute_shader ,
2014-08-26 20:56:53 -07:00
ARB_conservative_depth ,
2015-10-15 16:38:59 -07:00
ARB_copy_image ,
2014-03-04 22:20:37 -08:00
ARB_debug_label ,
2013-07-21 19:27:47 -07:00
ARB_debug_output ,
2014-08-26 20:56:53 -07:00
ARB_depth_buffer_float ,
2013-07-28 19:16:35 -07:00
ARB_depth_clamp ,
2014-03-12 22:32:27 -07:00
ARB_draw_buffers_blend ,
2015-04-29 23:20:21 -07:00
ARB_draw_indirect ,
2014-08-26 20:56:53 -07:00
ARB_draw_instanced ,
2013-09-04 21:42:31 -07:00
ARB_ES3_compatibility ,
2014-02-18 23:36:13 -08:00
ARB_framebuffer_object ,
2013-07-21 19:27:47 -07:00
ARB_framebuffer_sRGB ,
ARB_get_program_binary ,
2013-12-20 21:42:24 -08:00
ARB_half_float_pixel ,
2013-07-21 19:27:47 -07:00
ARB_half_float_vertex ,
ARB_instanced_arrays ,
2015-09-01 13:23:20 -07:00
ARB_internalformat_query ,
ARB_internalformat_query2 ,
2015-01-11 18:00:08 -08:00
ARB_invalidate_subdata ,
2014-02-26 20:24:35 -08:00
ARB_map_buffer_range ,
2015-04-29 23:20:21 -07:00
ARB_multi_draw_indirect ,
2013-07-21 19:27:47 -07:00
ARB_multisample ,
2014-08-26 20:56:53 -07:00
ARB_occlusion_query ,
ARB_occlusion_query2 ,
2014-07-20 20:27:13 -07:00
ARB_program_interface_query ,
2013-07-24 21:59:59 -07:00
ARB_sampler_objects ,
2013-07-21 19:59:42 -07:00
ARB_seamless_cube_map ,
2014-08-26 20:56:53 -07:00
ARB_shader_bit_encoding ,
2014-07-20 20:27:13 -07:00
ARB_shader_image_load_store ,
ARB_shader_storage_buffer_object ,
2014-02-09 16:46:50 -08:00
ARB_shader_texture_lod ,
2014-08-01 19:24:42 -07:00
ARB_texture_compression_bptc ,
2014-01-12 13:51:26 -08:00
ARB_texture_compression_rgtc ,
2013-07-21 19:27:47 -07:00
ARB_texture_float ,
ARB_texture_multisample ,
2014-08-01 19:24:42 -07:00
ARB_texture_rg ,
ARB_texture_rgb10_a2ui ,
ARB_texture_stencil8 ,
2014-02-26 20:24:35 -08:00
ARB_texture_storage ,
2013-07-21 19:27:47 -07:00
ARB_texture_swizzle ,
ARB_timer_query ,
2014-02-26 20:24:35 -08:00
ARB_uniform_buffer_object ,
2013-07-21 19:27:47 -07:00
ARB_vertex_array_object ,
ARB_vertex_type_2_10_10_10_rev ,
2014-02-19 23:49:28 -08:00
2013-07-21 19:27:47 -07:00
ATI_meminfo ,
2014-02-19 23:49:28 -08:00
2014-09-12 00:02:12 -07:00
CHROMIUM_color_buffer_float_rgb ,
CHROMIUM_color_buffer_float_rgba ,
2014-01-12 13:51:26 -08:00
CHROMIUM_depth_texture ,
2013-07-21 19:27:47 -07:00
CHROMIUM_framebuffer_multisample ,
2012-12-30 20:52:47 -08:00
CHROMIUM_texture_compression_dxt3 ,
CHROMIUM_texture_compression_dxt5 ,
2014-02-19 23:49:28 -08:00
2013-07-21 19:27:47 -07:00
EXT_bgra ,
EXT_blend_color ,
EXT_blend_minmax ,
EXT_blend_subtract ,
2015-03-22 22:03:37 -07:00
EXT_color_buffer_half_float ,
2015-03-28 21:41:48 -07:00
EXT_color_buffer_float ,
2015-10-15 16:38:59 -07:00
EXT_copy_image ,
2014-07-27 20:44:02 -07:00
EXT_compressed_ETC1_RGB8_sub_texture ,
2014-02-26 20:24:35 -08:00
EXT_debug_label ,
EXT_debug_marker ,
2015-05-08 11:49:18 -07:00
EXT_debug_tool ,
2015-01-11 18:00:08 -08:00
EXT_discard_framebuffer ,
2015-03-30 00:06:34 -07:00
EXT_disjoint_timer_query ,
2014-09-12 00:02:12 -07:00
EXT_draw_buffers ,
2016-03-10 23:41:33 -08:00
EXT_draw_instanced ,
EXT_instanced_arrays ,
2013-12-13 23:06:28 -08:00
EXT_frag_depth ,
2013-07-21 19:27:47 -07:00
EXT_framebuffer_blit ,
2014-02-18 23:36:13 -08:00
EXT_framebuffer_object ,
2013-07-21 19:27:47 -07:00
EXT_framebuffer_sRGB ,
2016-03-22 23:01:23 -07:00
EXT_gpu_shader4 ,
2015-04-29 23:20:21 -07:00
EXT_multi_draw_indirect ,
2013-07-21 19:27:47 -07:00
EXT_occlusion_query_boolean ,
2014-08-26 20:56:53 -07:00
EXT_packed_float ,
2014-03-04 22:20:37 -08:00
EXT_read_format_bgra ,
2014-07-20 20:27:13 -07:00
EXT_shader_image_load_store ,
2014-02-16 16:08:44 -08:00
EXT_shader_texture_lod ,
2014-02-09 16:46:50 -08:00
EXT_shadow_samplers ,
2015-11-30 14:50:28 -08:00
EXT_sRGB_write_control ,
2013-12-20 21:42:24 -08:00
EXT_texture_array ,
2013-07-21 19:27:47 -07:00
EXT_texture_compression_dxt1 ,
2013-01-20 12:47:29 -08:00
EXT_texture_compression_latc ,
2013-01-22 20:34:08 -08:00
EXT_texture_compression_rgtc ,
2013-07-21 19:27:47 -07:00
EXT_texture_compression_s3tc ,
EXT_texture_filter_anisotropic ,
EXT_texture_format_BGRA8888 ,
2014-07-25 23:16:11 -07:00
EXT_texture_rg ,
2015-09-29 16:06:06 -07:00
EXT_texture_shared_exponent ,
2015-08-27 16:35:27 -07:00
EXT_texture_snorm ,
2013-07-21 19:27:47 -07:00
EXT_texture_sRGB ,
EXT_texture_storage ,
EXT_texture_swizzle ,
EXT_texture_type_2_10_10_10_REV ,
EXT_timer_query ,
2013-11-07 22:59:17 -08:00
EXT_unpack_subimage ,
2014-02-19 23:49:28 -08:00
2014-01-12 13:51:26 -08:00
GOOGLE_depth_texture ,
2014-02-19 23:49:28 -08:00
2014-03-04 22:20:37 -08:00
GREMEDY_string_marker ,
GREMEDY_frame_terminator ,
2013-09-02 16:22:53 -07:00
IMG_multisampled_render_to_texture ,
2013-09-03 20:13:07 -07:00
IMG_read_format ,
2013-09-02 16:22:53 -07:00
IMG_shader_binary ,
IMG_texture_compression_pvrtc ,
2013-09-03 20:13:07 -07:00
IMG_texture_compression_pvrtc2 ,
2013-09-02 16:22:53 -07:00
IMG_texture_format_BGRA8888 ,
2014-02-19 23:49:28 -08:00
2014-07-20 20:27:13 -07:00
INTEL_fragment_shader_ordering ,
2014-03-04 22:20:37 -08:00
KHR_debug ,
2015-05-10 11:45:49 -07:00
KHR_no_error ,
2014-03-04 22:20:37 -08:00
2014-03-16 17:43:51 -07:00
MOZ_WEBGL_compressed_texture_s3tc ,
MOZ_WEBGL_depth_texture ,
2016-03-16 20:04:06 -07:00
NV_conservative_raster ,
2015-10-15 16:38:59 -07:00
NV_copy_image ,
2014-03-27 22:36:53 -07:00
NV_draw_buffers ,
2015-11-01 19:12:42 -08:00
NV_occlusion_query ,
2015-10-15 16:38:59 -07:00
NV_texture_border_clamp ,
2013-07-21 19:27:47 -07:00
NVX_gpu_memory_info ,
2014-02-19 23:49:28 -08:00
2015-10-15 16:38:59 -07:00
OES_copy_image ,
2013-09-02 16:22:53 -07:00
OES_compressed_ETC1_RGB8_texture ,
2013-12-13 23:52:35 -08:00
OES_depth24 ,
2013-12-29 11:43:44 -08:00
OES_depth32 ,
2013-09-02 16:22:53 -07:00
OES_depth_texture ,
2015-04-08 19:59:48 -07:00
OES_element_index_uint ,
2013-12-13 23:06:28 -08:00
OES_fragment_precision_high ,
2013-07-21 19:27:47 -07:00
OES_get_program_binary ,
2013-12-29 11:43:44 -08:00
OES_required_internalformat ,
OES_packed_depth_stencil ,
2013-09-03 20:13:07 -07:00
OES_read_format ,
2013-07-21 19:27:47 -07:00
OES_rgb8_rgba8 ,
OES_standard_derivatives ,
2013-12-12 22:35:27 -08:00
OES_texture_3D ,
2012-12-30 20:52:47 -08:00
OES_texture_float ,
OES_texture_float_linear ,
2013-12-13 23:52:35 -08:00
OES_texture_npot ,
2012-12-30 20:52:47 -08:00
OES_texture_half_float ,
OES_texture_half_float_linear ,
2015-02-26 17:51:00 -08:00
OES_texture_stencil8 ,
2013-07-21 19:27:47 -07:00
OES_vertex_array_object ,
2012-12-30 20:52:47 -08:00
OES_vertex_half_float ,
OES_vertex_type_10_10_10_2 ,
2015-03-22 22:03:37 -07:00
WEBGL_color_buffer_float ,
2014-04-15 22:59:40 -07:00
WEBGL_compressed_texture_etc1 ,
2014-03-16 17:43:51 -07:00
WEBGL_compressed_texture_s3tc ,
2014-04-15 22:59:40 -07:00
WEBGL_compressed_texture_pvrtc ,
2014-03-16 17:43:51 -07:00
WEBGL_depth_texture ,
2015-03-22 22:03:37 -07:00
WEBGL_draw_buffers ,
2014-03-16 17:43:51 -07:00
WEBKIT_EXT_texture_filter_anisotropic ,
WEBKIT_WEBGL_compressed_texture_s3tc ,
WEBKIT_WEBGL_depth_texture ,
2012-12-30 20:52:47 -08:00
Count
} ;
const char * m_name ;
bool m_supported ;
bool m_initialize ;
} ;
2015-03-31 09:44:51 -07:00
// Extension registry
//
// ANGLE:
// https://github.com/google/angle/tree/master/extensions
//
// CHROMIUM:
// https://chromium.googlesource.com/chromium/src.git/+/refs/heads/git-svn/gpu/GLES2/extensions/CHROMIUM
//
// EGL:
// https://www.khronos.org/registry/egl/extensions/
//
// GL:
// https://www.opengl.org/registry/
//
// GLES:
// https://www.khronos.org/registry/gles/extensions/
//
// WEBGL:
// https://www.khronos.org/registry/webgl/extensions/
//
2015-03-30 00:06:34 -07:00
static Extension s_extension [ ] =
2012-12-30 20:52:47 -08:00
{
2014-08-26 20:56:53 -07:00
{ " AMD_conservative_depth " , false , true } ,
2015-04-29 23:20:21 -07:00
{ " AMD_multi_draw_indirect " , false , true } ,
2014-08-26 20:56:53 -07:00
2014-03-16 17:43:51 -07:00
{ " ANGLE_depth_texture " , false , true } ,
{ " ANGLE_framebuffer_blit " , false , true } ,
{ " ANGLE_framebuffer_multisample " , false , false } ,
{ " ANGLE_instanced_arrays " , false , true } ,
{ " ANGLE_texture_compression_dxt1 " , false , true } ,
{ " ANGLE_texture_compression_dxt3 " , false , true } ,
{ " ANGLE_texture_compression_dxt5 " , false , true } ,
2015-03-30 00:06:34 -07:00
{ " ANGLE_timer_query " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " ANGLE_translated_shader_source " , false , true } ,
{ " APPLE_texture_format_BGRA8888 " , false , true } ,
{ " APPLE_texture_max_level " , false , true } ,
2014-07-20 20:27:13 -07:00
{ " ARB_compute_shader " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2014-08-26 20:56:53 -07:00
{ " ARB_conservative_depth " , BGFX_CONFIG_RENDERER_OPENGL > = 42 , true } ,
2015-10-15 16:38:59 -07:00
{ " ARB_copy_image " , BGFX_CONFIG_RENDERER_OPENGL > = 42 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_debug_label " , false , true } ,
{ " ARB_debug_output " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2014-08-26 20:56:53 -07:00
{ " ARB_depth_buffer_float " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_depth_clamp " , BGFX_CONFIG_RENDERER_OPENGL > = 32 , true } ,
{ " ARB_draw_buffers_blend " , BGFX_CONFIG_RENDERER_OPENGL > = 40 , true } ,
2015-04-29 23:20:21 -07:00
{ " ARB_draw_indirect " , BGFX_CONFIG_RENDERER_OPENGL > = 40 , true } ,
2014-08-26 20:56:53 -07:00
{ " ARB_draw_instanced " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_ES3_compatibility " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
{ " ARB_framebuffer_object " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_framebuffer_sRGB " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_get_program_binary " , BGFX_CONFIG_RENDERER_OPENGL > = 41 , true } ,
{ " ARB_half_float_pixel " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_half_float_vertex " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_instanced_arrays " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
2015-09-01 13:23:20 -07:00
{ " ARB_internalformat_query " , BGFX_CONFIG_RENDERER_OPENGL > = 42 , true } ,
{ " ARB_internalformat_query2 " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2015-01-11 18:00:08 -08:00
{ " ARB_invalidate_subdata " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_map_buffer_range " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
2015-04-29 23:20:21 -07:00
{ " ARB_multi_draw_indirect " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_multisample " , false , true } ,
2014-08-26 20:56:53 -07:00
{ " ARB_occlusion_query " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
{ " ARB_occlusion_query2 " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
2014-07-20 20:27:13 -07:00
{ " ARB_program_interface_query " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_sampler_objects " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
{ " ARB_seamless_cube_map " , BGFX_CONFIG_RENDERER_OPENGL > = 32 , true } ,
2014-08-26 20:56:53 -07:00
{ " ARB_shader_bit_encoding " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
2014-07-20 20:27:13 -07:00
{ " ARB_shader_image_load_store " , BGFX_CONFIG_RENDERER_OPENGL > = 42 , true } ,
{ " ARB_shader_storage_buffer_object " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_shader_texture_lod " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
2014-08-01 19:24:42 -07:00
{ " ARB_texture_compression_bptc " , BGFX_CONFIG_RENDERER_OPENGL > = 44 , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_texture_compression_rgtc " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_texture_float " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_texture_multisample " , BGFX_CONFIG_RENDERER_OPENGL > = 32 , true } ,
2014-08-01 19:24:42 -07:00
{ " ARB_texture_rg " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_texture_rgb10_a2ui " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
{ " ARB_texture_stencil8 " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " ARB_texture_storage " , BGFX_CONFIG_RENDERER_OPENGL > = 42 , true } ,
{ " ARB_texture_swizzle " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
{ " ARB_timer_query " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
{ " ARB_uniform_buffer_object " , BGFX_CONFIG_RENDERER_OPENGL > = 31 , true } ,
{ " ARB_vertex_array_object " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " ARB_vertex_type_2_10_10_10_rev " , false , true } ,
{ " ATI_meminfo " , false , true } ,
2014-09-12 00:02:12 -07:00
{ " CHROMIUM_color_buffer_float_rgb " , false , true } ,
{ " CHROMIUM_color_buffer_float_rgba " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " CHROMIUM_depth_texture " , false , true } ,
{ " CHROMIUM_framebuffer_multisample " , false , true } ,
{ " CHROMIUM_texture_compression_dxt3 " , false , true } ,
{ " CHROMIUM_texture_compression_dxt5 " , false , true } ,
{ " EXT_bgra " , false , true } ,
{ " EXT_blend_color " , BGFX_CONFIG_RENDERER_OPENGL > = 31 , true } ,
{ " EXT_blend_minmax " , BGFX_CONFIG_RENDERER_OPENGL > = 14 , true } ,
{ " EXT_blend_subtract " , BGFX_CONFIG_RENDERER_OPENGL > = 14 , true } ,
2015-03-22 22:03:37 -07:00
{ " EXT_color_buffer_half_float " , false , true } , // GLES2 extension.
2015-03-28 21:41:48 -07:00
{ " EXT_color_buffer_float " , false , true } , // GLES2 extension.
2015-10-15 16:38:59 -07:00
{ " EXT_copy_image " , false , true } , // GLES2 extension.
2014-07-27 20:44:02 -07:00
{ " EXT_compressed_ETC1_RGB8_sub_texture " , false , true } , // GLES2 extension.
2014-03-16 17:43:51 -07:00
{ " EXT_debug_label " , false , true } ,
{ " EXT_debug_marker " , false , true } ,
2015-05-08 11:49:18 -07:00
{ " EXT_debug_tool " , false , true } , // RenderDoc extension.
2015-01-11 18:00:08 -08:00
{ " EXT_discard_framebuffer " , false , true } , // GLES2 extension.
2015-03-30 00:06:34 -07:00
{ " EXT_disjoint_timer_query " , false , true } , // GLES2 extension.
2014-09-12 00:02:12 -07:00
{ " EXT_draw_buffers " , false , true } , // GLES2 extension.
2016-03-10 23:41:33 -08:00
{ " EXT_draw_instanced " , false , true } , // GLES2 extension.
{ " EXT_instanced_arrays " , false , true } , // GLES2 extension.
2014-03-16 17:43:51 -07:00
{ " EXT_frag_depth " , false , true } , // GLES2 extension.
{ " EXT_framebuffer_blit " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " EXT_framebuffer_object " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " EXT_framebuffer_sRGB " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
2016-03-22 23:01:23 -07:00
{ " EXT_gpu_shader4 " , false , true } ,
2015-04-29 23:20:21 -07:00
{ " EXT_multi_draw_indirect " , false , true } , // GLES3.1 extension.
2015-11-01 19:12:42 -08:00
{ " EXT_occlusion_query_boolean " , false , true } , // GLES2 extension.
2014-08-26 20:56:53 -07:00
{ " EXT_packed_float " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
2014-03-16 17:43:51 -07:00
{ " EXT_read_format_bgra " , false , true } ,
2014-07-20 20:27:13 -07:00
{ " EXT_shader_image_load_store " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " EXT_shader_texture_lod " , false , true } , // GLES2 extension.
{ " EXT_shadow_samplers " , false , true } ,
2015-11-30 14:50:28 -08:00
{ " EXT_sRGB_write_control " , false , true } , // GLES2 extension.
2014-03-16 17:43:51 -07:00
{ " EXT_texture_array " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " EXT_texture_compression_dxt1 " , false , true } ,
{ " EXT_texture_compression_latc " , false , true } ,
{ " EXT_texture_compression_rgtc " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " EXT_texture_compression_s3tc " , false , true } ,
{ " EXT_texture_filter_anisotropic " , false , true } ,
{ " EXT_texture_format_BGRA8888 " , false , true } ,
2014-07-25 23:16:11 -07:00
{ " EXT_texture_rg " , false , true } , // GLES2 extension.
2015-09-29 16:06:06 -07:00
{ " EXT_texture_shared_exponent " , false , true } ,
2015-08-27 16:35:27 -07:00
{ " EXT_texture_snorm " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
2014-03-16 17:43:51 -07:00
{ " EXT_texture_sRGB " , false , true } ,
{ " EXT_texture_storage " , false , true } ,
{ " EXT_texture_swizzle " , false , true } ,
{ " EXT_texture_type_2_10_10_10_REV " , false , true } ,
2015-03-30 00:06:34 -07:00
{ " EXT_timer_query " , BGFX_CONFIG_RENDERER_OPENGL > = 33 , true } ,
2014-03-16 17:43:51 -07:00
{ " EXT_unpack_subimage " , false , true } ,
{ " GOOGLE_depth_texture " , false , true } ,
{ " GREMEDY_string_marker " , false , true } ,
{ " GREMEDY_frame_terminator " , false , true } ,
{ " IMG_multisampled_render_to_texture " , false , true } ,
{ " IMG_read_format " , false , true } ,
{ " IMG_shader_binary " , false , true } ,
{ " IMG_texture_compression_pvrtc " , false , true } ,
{ " IMG_texture_compression_pvrtc2 " , false , true } ,
{ " IMG_texture_format_BGRA8888 " , false , true } ,
2014-07-20 20:27:13 -07:00
{ " INTEL_fragment_shader_ordering " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " KHR_debug " , BGFX_CONFIG_RENDERER_OPENGL > = 43 , true } ,
2015-05-10 11:45:49 -07:00
{ " KHR_no_error " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " MOZ_WEBGL_compressed_texture_s3tc " , false , true } ,
{ " MOZ_WEBGL_depth_texture " , false , true } ,
2016-03-16 20:04:06 -07:00
{ " NV_conservative_raster " , false , true } ,
2015-10-15 16:38:59 -07:00
{ " NV_copy_image " , false , true } ,
2014-03-27 22:36:53 -07:00
{ " NV_draw_buffers " , false , true } , // GLES2 extension.
2015-11-01 19:12:42 -08:00
{ " NV_occlusion_query " , false , true } ,
2015-10-15 16:38:59 -07:00
{ " NV_texture_border_clamp " , false , true } , // GLES2 extension.
2014-03-16 17:43:51 -07:00
{ " NVX_gpu_memory_info " , false , true } ,
2015-10-15 16:38:59 -07:00
{ " OES_copy_image " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " OES_compressed_ETC1_RGB8_texture " , false , true } ,
{ " OES_depth24 " , false , true } ,
{ " OES_depth32 " , false , true } ,
{ " OES_depth_texture " , false , true } ,
2015-04-08 19:59:48 -07:00
{ " OES_element_index_uint " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " OES_fragment_precision_high " , false , true } ,
{ " OES_get_program_binary " , false , true } ,
{ " OES_required_internalformat " , false , true } ,
{ " OES_packed_depth_stencil " , false , true } ,
{ " OES_read_format " , false , true } ,
{ " OES_rgb8_rgba8 " , false , true } ,
{ " OES_standard_derivatives " , false , true } ,
{ " OES_texture_3D " , false , true } ,
{ " OES_texture_float " , false , true } ,
{ " OES_texture_float_linear " , false , true } ,
{ " OES_texture_npot " , false , true } ,
{ " OES_texture_half_float " , false , true } ,
{ " OES_texture_half_float_linear " , false , true } ,
2015-02-26 17:51:00 -08:00
{ " OES_texture_stencil8 " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " OES_vertex_array_object " , false , ! BX_PLATFORM_IOS } ,
{ " OES_vertex_half_float " , false , true } ,
{ " OES_vertex_type_10_10_10_2 " , false , true } ,
2015-03-22 22:03:37 -07:00
{ " WEBGL_color_buffer_float " , false , true } ,
2014-04-15 22:59:40 -07:00
{ " WEBGL_compressed_texture_etc1 " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " WEBGL_compressed_texture_s3tc " , false , true } ,
2014-04-15 22:59:40 -07:00
{ " WEBGL_compressed_texture_pvrtc " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " WEBGL_depth_texture " , false , true } ,
2015-03-22 22:03:37 -07:00
{ " WEBGL_draw_buffers " , false , true } ,
2014-03-16 17:43:51 -07:00
{ " WEBKIT_EXT_texture_filter_anisotropic " , false , true } ,
{ " WEBKIT_WEBGL_compressed_texture_s3tc " , false , true } ,
{ " WEBKIT_WEBGL_depth_texture " , false , true } ,
2012-12-30 20:52:47 -08:00
} ;
2015-03-30 00:06:34 -07:00
BX_STATIC_ASSERT ( Extension : : Count = = BX_COUNTOF ( s_extension ) ) ;
2012-12-30 20:52:47 -08:00
2014-02-09 16:46:50 -08:00
static const char * s_ARB_shader_texture_lod [ ] =
{
" texture2DLod " ,
" texture2DProjLod " ,
" texture3DLod " ,
" texture3DProjLod " ,
" textureCubeLod " ,
" shadow2DLod " ,
" shadow2DProjLod " ,
NULL
// "texture1DLod",
// "texture1DProjLod",
// "shadow1DLod",
// "shadow1DProjLod",
} ;
2014-02-16 16:08:44 -08:00
static const char * s_EXT_shader_texture_lod [ ] =
{
" texture2DLod " ,
" texture2DProjLod " ,
" textureCubeLod " ,
NULL
// "texture2DGrad",
// "texture2DProjGrad",
// "textureCubeGrad",
} ;
2014-02-09 16:46:50 -08:00
static const char * s_EXT_shadow_samplers [ ] =
{
" shadow2D " ,
" shadow2DProj " ,
NULL
} ;
static const char * s_OES_standard_derivatives [ ] =
{
" dFdx " ,
" dFdy " ,
" fwidth " ,
NULL
} ;
static const char * s_OES_texture_3D [ ] =
{
" texture3D " ,
" texture3DProj " ,
" texture3DLod " ,
" texture3DProjLod " ,
NULL
} ;
2015-03-16 21:44:33 -07:00
static const char * s_uisamplers [ ] =
{
" isampler2D " ,
" usampler2D " ,
" isampler3D " ,
" usampler3D " ,
" isamplerCube " ,
" usamplerCube " ,
2015-03-17 15:38:41 -07:00
NULL
2015-03-16 21:44:33 -07:00
} ;
2012-07-08 12:28:38 -07:00
static void GL_APIENTRY stubVertexAttribDivisor ( GLuint /*_index*/ , GLuint /*_divisor*/ )
{
}
2012-07-08 19:10:07 -07:00
2012-07-08 12:28:38 -07:00
static void GL_APIENTRY stubDrawArraysInstanced ( GLenum _mode , GLint _first , GLsizei _count , GLsizei /*_primcount*/ )
{
2013-02-23 00:15:54 -08:00
GL_CHECK ( glDrawArrays ( _mode , _first , _count ) ) ;
2012-07-08 12:28:38 -07:00
}
static void GL_APIENTRY stubDrawElementsInstanced ( GLenum _mode , GLsizei _count , GLenum _type , const GLvoid * _indices , GLsizei /*_primcount*/ )
{
2013-02-23 00:15:54 -08:00
GL_CHECK ( glDrawElements ( _mode , _count , _type , _indices ) ) ;
2012-07-08 12:28:38 -07:00
}
2014-03-04 22:20:37 -08:00
static void GL_APIENTRY stubFrameTerminatorGREMEDY ( )
{
}
2012-07-08 19:10:07 -07:00
2014-03-04 22:20:37 -08:00
static void GL_APIENTRY stubInsertEventMarker ( GLsizei /*_length*/ , const char * /*_marker*/ )
2013-06-09 15:28:25 -07:00
{
}
2014-03-04 22:20:37 -08:00
static void GL_APIENTRY stubInsertEventMarkerGREMEDY ( GLsizei _length , const char * _marker )
2013-06-09 15:28:25 -07:00
{
2014-03-04 22:20:37 -08:00
// If <marker> is a null-terminated string then <length> should not
// include the terminator.
//
// If <length> is 0 then <marker> is assumed to be null-terminated.
2014-03-12 22:32:27 -07:00
uint32_t size = ( 0 = = _length ? ( uint32_t ) strlen ( _marker ) : _length ) + 1 ;
2014-03-04 22:20:37 -08:00
size * = sizeof ( wchar_t ) ;
wchar_t * name = ( wchar_t * ) alloca ( size ) ;
mbstowcs ( name , _marker , size - 2 ) ;
GL_CHECK ( glStringMarkerGREMEDY ( _length , _marker ) ) ;
2013-06-09 15:28:25 -07:00
}
2014-03-09 21:20:34 -07:00
static void GL_APIENTRY stubObjectLabel ( GLenum /*_identifier*/ , GLuint /*_name*/ , GLsizei /*_length*/ , const char * /*_label*/ )
{
}
2015-01-11 18:00:08 -08:00
static void GL_APIENTRY stubInvalidateFramebuffer ( GLenum /*_target*/ , GLsizei /*_numAttachments*/ , const GLenum * /*_attachments*/ )
{
}
2015-04-30 18:06:41 -07:00
static void GL_APIENTRY stubMultiDrawArraysIndirect ( GLenum _mode , const void * _indirect , GLsizei _drawcount , GLsizei _stride )
{
const uint8_t * args = ( const uint8_t * ) _indirect ;
for ( GLsizei ii = 0 ; ii < _drawcount ; + + ii )
{
GL_CHECK ( glDrawArraysIndirect ( _mode , ( void * ) args ) ) ;
args + = _stride ;
}
}
static void GL_APIENTRY stubMultiDrawElementsIndirect ( GLenum _mode , GLenum _type , const void * _indirect , GLsizei _drawcount , GLsizei _stride )
{
const uint8_t * args = ( const uint8_t * ) _indirect ;
for ( GLsizei ii = 0 ; ii < _drawcount ; + + ii )
{
GL_CHECK ( glDrawElementsIndirect ( _mode , _type , ( void * ) args ) ) ;
args + = _stride ;
}
}
2012-07-08 19:10:07 -07:00
typedef void ( * PostSwapBuffersFn ) ( uint32_t _width , uint32_t _height ) ;
2013-04-20 23:13:44 -07:00
static const char * getGLString ( GLenum _name )
{
const char * str = ( const char * ) glGetString ( _name ) ;
glGetError ( ) ; // ignore error if glGetString returns NULL.
if ( NULL ! = str )
{
return str ;
}
return " <unknown> " ;
}
static uint32_t getGLStringHash ( GLenum _name )
{
const char * str = ( const char * ) glGetString ( _name ) ;
glGetError ( ) ; // ignore error if glGetString returns NULL.
if ( NULL ! = str )
{
2013-04-24 19:15:29 -07:00
return bx : : hashMurmur2A ( str , ( uint32_t ) strlen ( str ) ) ;
2013-04-20 23:13:44 -07:00
}
return 0 ;
}
2013-04-26 23:43:31 -07:00
void dumpExtensions ( const char * _extensions )
{
if ( NULL ! = _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 )
{
2013-08-03 22:15:13 -07:00
len = bx : : uint32_min ( sizeof ( name ) , ( uint32_t ) ( space - pos ) ) ;
2013-04-26 23:43:31 -07:00
}
else
{
2013-08-03 22:15:13 -07:00
len = bx : : uint32_min ( sizeof ( name ) , ( uint32_t ) strlen ( pos ) ) ;
2013-04-26 23:43:31 -07:00
}
strncpy ( name , pos , len ) ;
name [ len ] = ' \0 ' ;
BX_TRACE ( " \t %s " , name ) ;
pos + = len + 1 ;
}
}
}
2013-04-20 23:13:44 -07:00
const char * toString ( GLenum _enum )
2013-04-15 20:59:01 -07:00
{
switch ( _enum )
{
2015-04-21 20:30:31 -07:00
case GL_DEBUG_SOURCE_API : return " API " ;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM : return " WinSys " ;
case GL_DEBUG_SOURCE_SHADER_COMPILER : return " Shader " ;
case GL_DEBUG_SOURCE_THIRD_PARTY : return " 3rdparty " ;
case GL_DEBUG_SOURCE_APPLICATION : return " Application " ;
case GL_DEBUG_SOURCE_OTHER : return " Other " ;
case GL_DEBUG_TYPE_ERROR : return " Error " ;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR : return " Deprecated behavior " ;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR : return " Undefined behavior " ;
case GL_DEBUG_TYPE_PORTABILITY : return " Portability " ;
case GL_DEBUG_TYPE_PERFORMANCE : return " Performance " ;
case GL_DEBUG_TYPE_OTHER : return " Other " ;
case GL_DEBUG_SEVERITY_HIGH : return " High " ;
case GL_DEBUG_SEVERITY_MEDIUM : return " Medium " ;
case GL_DEBUG_SEVERITY_LOW : return " Low " ;
2013-04-15 20:59:01 -07:00
default :
break ;
}
return " <unknown> " ;
}
2014-03-30 21:54:53 -07:00
void GL_APIENTRY debugProcCb ( GLenum _source , GLenum _type , GLuint _id , GLenum _severity , GLsizei /*_length*/ , const GLchar * _message , const void * /*_userParam*/ )
2013-04-07 22:12:34 -07:00
{
2013-04-15 20:59:01 -07:00
BX_TRACE ( " src %s, type %s, id %d, severity %s, '%s' "
, toString ( _source )
, toString ( _type )
2013-04-07 22:12:34 -07:00
, _id
2013-04-15 20:59:01 -07:00
, toString ( _severity )
2013-04-07 22:12:34 -07:00
, _message
) ;
2013-04-23 19:29:46 -07:00
BX_UNUSED ( _source , _type , _id , _severity , _message ) ;
2013-04-07 22:12:34 -07:00
}
2014-03-04 22:20:37 -08:00
GLint glGet ( GLenum _pname )
{
GLint result = 0 ;
glGetIntegerv ( _pname , & result ) ;
GLenum err = glGetError ( ) ;
BX_WARN ( 0 = = err , " glGetIntegerv(0x%04x, ...) failed with GL error: 0x%04x. " , _pname , err ) ;
return 0 = = err ? result : 0 ;
}
2014-04-06 21:30:32 -07:00
void setTextureFormat ( TextureFormat : : Enum _format , GLenum _internalFmt , GLenum _fmt , GLenum _type = GL_ZERO )
2014-04-02 20:52:15 -07:00
{
2014-04-06 21:30:32 -07:00
TextureFormatInfo & tfi = s_textureFormat [ _format ] ;
tfi . m_internalFmt = _internalFmt ;
tfi . m_fmt = _fmt ;
tfi . m_type = _type ;
}
2015-05-18 12:39:42 -07:00
void initTestTexture ( TextureFormat : : Enum _format , bool srgb = false )
{
const TextureFormatInfo & tfi = s_textureFormat [ _format ] ;
GLenum internalFmt = srgb
? tfi . m_internalFmtSrgb
: tfi . m_internalFmt
;
GLsizei size = ( 16 * 16 * getBitsPerPixel ( _format ) ) / 8 ;
2015-10-08 17:34:03 -07:00
void * data = bx : : alignPtr ( alloca ( size + 16 ) , 0 , 16 ) ;
2015-05-18 12:39:42 -07:00
if ( isCompressed ( _format ) )
{
glCompressedTexImage2D ( GL_TEXTURE_2D , 0 , internalFmt , 16 , 16 , 0 , size , data ) ;
}
else
{
glTexImage2D ( GL_TEXTURE_2D , 0 , internalFmt , 16 , 16 , 0 , tfi . m_fmt , tfi . m_type , data ) ;
}
}
2015-05-18 14:35:05 -07:00
static bool isTextureFormatValid ( TextureFormat : : Enum _format , bool srgb = false )
2014-04-06 21:30:32 -07:00
{
2014-12-11 20:17:38 -08:00
const TextureFormatInfo & tfi = s_textureFormat [ _format ] ;
2015-05-04 20:57:22 -07:00
GLenum internalFmt = srgb
? tfi . m_internalFmtSrgb
: tfi . m_internalFmt
;
2015-09-23 20:03:59 -07:00
if ( GL_ZERO = = internalFmt )
2014-12-11 20:17:38 -08:00
{
return false ;
}
2014-04-06 21:30:32 -07:00
GLuint id ;
GL_CHECK ( glGenTextures ( 1 , & id ) ) ;
GL_CHECK ( glBindTexture ( GL_TEXTURE_2D , id ) ) ;
2015-05-18 12:39:42 -07:00
initTestTexture ( _format ) ;
2014-04-10 19:21:10 -07:00
2015-05-18 12:39:42 -07:00
GLenum err = glGetError ( ) ;
BX_WARN ( 0 = = err , " TextureFormat::%s is not supported (%x: %s). " , getName ( _format ) , err , glEnumName ( err ) ) ;
GL_CHECK ( glDeleteTextures ( 1 , & id ) ) ;
return 0 = = err ;
}
2015-05-18 14:35:05 -07:00
static bool isImageFormatValid ( TextureFormat : : Enum _format )
{
if ( GL_ZERO = = s_imageFormat [ _format ] )
{
return false ;
}
GLuint id ;
GL_CHECK ( glGenTextures ( 1 , & id ) ) ;
GL_CHECK ( glBindTexture ( GL_TEXTURE_2D , id ) ) ;
2015-08-28 11:17:26 -07:00
glTexStorage2D ( GL_TEXTURE_2D , 1 , s_imageFormat [ _format ] , 16 , 16 ) ;
2015-05-18 14:35:05 -07:00
GLenum err = glGetError ( ) ;
2015-08-28 11:17:26 -07:00
if ( 0 = = err )
{
glBindImageTexture ( 0
, id
, 0
, GL_FALSE
, 0
, GL_READ_WRITE
, s_imageFormat [ _format ]
) ;
err = glGetError ( ) ;
}
2015-05-18 14:35:05 -07:00
GL_CHECK ( glDeleteTextures ( 1 , & id ) ) ;
return 0 = = err ;
}
static bool isFramebufferFormatValid ( TextureFormat : : Enum _format , bool srgb = false )
2015-05-18 12:39:42 -07:00
{
const TextureFormatInfo & tfi = s_textureFormat [ _format ] ;
GLenum internalFmt = srgb
? tfi . m_internalFmtSrgb
: tfi . m_internalFmt
;
if ( GL_ZERO = = internalFmt
| | ! tfi . m_supported )
2014-04-02 20:52:15 -07:00
{
2015-05-18 12:39:42 -07:00
return false ;
}
GLuint fbo ;
GL_CHECK ( glGenFramebuffers ( 1 , & fbo ) ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , fbo ) ) ;
GLuint id ;
GL_CHECK ( glGenTextures ( 1 , & id ) ) ;
GL_CHECK ( glBindTexture ( GL_TEXTURE_2D , id ) ) ;
initTestTexture ( _format ) ;
GLenum err = glGetError ( ) ;
GLenum attachment ;
if ( isDepth ( _format ) )
{
const ImageBlockInfo & info = getBlockInfo ( _format ) ;
2015-08-04 08:40:14 -07:00
if ( 0 = = info . depthBits )
2015-05-18 12:39:42 -07:00
{
2015-08-04 08:40:14 -07:00
attachment = GL_STENCIL_ATTACHMENT ;
2015-05-18 12:39:42 -07:00
}
2015-08-04 08:40:14 -07:00
else if ( 0 = = info . stencilBits )
2015-05-18 12:39:42 -07:00
{
2015-08-04 08:40:14 -07:00
attachment = GL_DEPTH_ATTACHMENT ;
2015-05-18 12:39:42 -07:00
}
else
{
2015-08-04 08:40:14 -07:00
attachment = GL_DEPTH_STENCIL_ATTACHMENT ;
2015-05-18 12:39:42 -07:00
}
2014-04-02 20:52:15 -07:00
}
2014-04-06 21:30:32 -07:00
else
{
2015-05-18 12:39:42 -07:00
attachment = GL_COLOR_ATTACHMENT0 ;
2014-04-06 21:30:32 -07:00
}
2015-05-18 12:39:42 -07:00
glFramebufferTexture2D ( GL_FRAMEBUFFER
, attachment
, GL_TEXTURE_2D
, id
, 0
) ;
err = glGetError ( ) ;
if ( 0 = = err )
{
err = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
}
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ) ;
GL_CHECK ( glDeleteFramebuffers ( 1 , & fbo ) ) ;
2014-04-06 21:30:32 -07:00
GL_CHECK ( glDeleteTextures ( 1 , & id ) ) ;
2015-05-18 12:39:42 -07:00
return GL_FRAMEBUFFER_COMPLETE = = err ;
2014-04-02 20:52:15 -07:00
}
2015-03-28 21:25:40 -07:00
static void getFilters ( uint32_t _flags , bool _hasMips , GLenum & _magFilter , GLenum & _minFilter )
{
const uint32_t mag = ( _flags & BGFX_TEXTURE_MAG_MASK ) > > BGFX_TEXTURE_MAG_SHIFT ;
const uint32_t min = ( _flags & BGFX_TEXTURE_MIN_MASK ) > > BGFX_TEXTURE_MIN_SHIFT ;
const uint32_t mip = ( _flags & BGFX_TEXTURE_MIP_MASK ) > > BGFX_TEXTURE_MIP_SHIFT ;
_magFilter = s_textureFilterMag [ mag ] ;
_minFilter = s_textureFilterMin [ min ] [ _hasMips ? mip + 1 : 0 ] ;
}
2016-01-05 21:06:42 -08:00
void updateExtension ( const char * _name )
{
bool supported = false ;
for ( uint32_t ii = 0 ; ii < Extension : : Count ; + + ii )
{
Extension & extension = s_extension [ ii ] ;
if ( ! extension . m_supported
& & extension . m_initialize )
{
const char * ext = _name ;
if ( 0 = = strncmp ( ext , " GL_ " , 3 ) ) // skip GL_
{
ext + = 3 ;
}
if ( 0 = = strcmp ( ext , extension . m_name ) )
{
extension . m_supported = true ;
supported = true ;
break ;
}
}
}
2016-01-05 22:54:10 -08:00
BX_TRACE ( " GL_EXTENSION %s: %s " , supported ? " (supported) " : " " , _name ) ;
2016-01-05 21:06:42 -08:00
BX_UNUSED ( supported ) ;
}
2014-05-26 14:09:26 -07:00
struct RendererContextGL : public RendererContextI
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
RendererContextGL ( )
2014-09-07 17:17:38 -07:00
: m_numWindows ( 1 )
, m_rtMsaa ( false )
2015-01-11 18:00:08 -08:00
, m_fbDiscard ( BGFX_CLEAR_NONE )
2013-02-18 22:30:11 -08:00
, m_capture ( NULL )
2012-12-30 20:52:47 -08:00
, m_captureSize ( 0 )
, m_maxAnisotropy ( 0.0f )
2015-01-21 20:39:42 -08:00
, m_maxAnisotropyDefault ( 0.0f )
2013-02-17 20:42:33 -08:00
, m_maxMsaa ( 0 )
2013-03-03 22:30:50 -08:00
, m_vao ( 0 )
2015-10-16 17:42:40 -07:00
, m_blitSupported ( false )
2015-10-20 19:57:44 -07:00
, m_readBackSupported ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
2014-02-23 11:21:23 -08:00
, m_vaoSupport ( false )
, m_samplerObjectSupport ( false )
, m_shadowSamplersSupport ( false )
2015-11-30 14:50:28 -08:00
, m_srgbWriteControlSupport ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
2015-09-12 09:25:37 -07:00
, m_borderColorSupport ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
2012-11-08 20:29:58 -08:00
, m_programBinarySupport ( false )
2013-01-06 12:39:18 -08:00
, m_textureSwizzleSupport ( false )
2014-01-12 13:51:26 -08:00
, m_depthTextureSupport ( false )
2015-03-30 00:06:34 -07:00
, m_timerQuerySupport ( false )
2015-11-01 19:12:42 -08:00
, m_occlusionQuerySupport ( false )
2016-03-16 20:04:06 -07:00
, m_atocSupport ( false )
, m_conservativeRasterSupport ( false )
2012-07-08 19:10:07 -07:00
, m_flip ( false )
, m_hash ( ( BX_PLATFORM_WINDOWS < < 1 ) | BX_ARCH_64BIT )
2013-02-20 22:13:32 -08:00
, m_backBufferFbo ( 0 )
2013-07-22 21:20:43 -07:00
, m_msaaBackBufferFbo ( 0 )
2014-10-28 22:08:55 -07:00
, m_ovrFbo ( 0 )
2014-10-13 21:14:51 -07:00
{
2014-10-28 21:41:34 -07:00
memset ( m_msaaBackBufferRbos , 0 , sizeof ( m_msaaBackBufferRbos ) ) ;
2014-10-13 21:14:51 -07:00
}
~ RendererContextGL ( )
{
}
void init ( )
2012-07-08 19:10:07 -07:00
{
2014-12-11 20:48:16 -08:00
m_renderdocdll = loadRenderDoc ( ) ;
2014-02-05 23:07:11 -08:00
m_fbh . idx = invalidHandle ;
2014-04-15 19:10:56 -07:00
memset ( m_uniforms , 0 , sizeof ( m_uniforms ) ) ;
2012-07-08 19:10:07 -07:00
memset ( & m_resolution , 0 , sizeof ( m_resolution ) ) ;
2013-02-20 22:13:32 -08:00
2014-05-26 14:09:26 -07:00
setRenderContextSize ( BGFX_DEFAULT_WIDTH , BGFX_DEFAULT_HEIGHT ) ;
2013-02-20 22:13:32 -08:00
2014-10-28 22:08:55 -07:00
// Must be after context is initialized?!
m_ovr . init ( ) ;
2015-08-28 11:17:26 -07:00
m_vendor = getGLString ( GL_VENDOR ) ;
m_renderer = getGLString ( GL_RENDERER ) ;
m_version = getGLString ( GL_VERSION ) ;
2014-05-26 14:09:26 -07:00
m_glslVersion = getGLString ( GL_SHADING_LANGUAGE_VERSION ) ;
2013-02-20 22:13:32 -08:00
2014-05-26 14:09:26 -07:00
GLint numCmpFormats = 0 ;
GL_CHECK ( glGetIntegerv ( GL_NUM_COMPRESSED_TEXTURE_FORMATS , & numCmpFormats ) ) ;
BX_TRACE ( " GL_NUM_COMPRESSED_TEXTURE_FORMATS %d " , numCmpFormats ) ;
2013-02-20 22:13:32 -08:00
2014-05-26 14:09:26 -07:00
GLint * cmpFormat = NULL ;
2013-02-20 22:13:32 -08:00
2014-05-26 14:09:26 -07:00
if ( 0 < numCmpFormats )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
numCmpFormats = numCmpFormats > 256 ? 256 : numCmpFormats ;
cmpFormat = ( GLint * ) alloca ( sizeof ( GLint ) * numCmpFormats ) ;
GL_CHECK ( glGetIntegerv ( GL_COMPRESSED_TEXTURE_FORMATS , cmpFormat ) ) ;
2014-02-20 23:03:31 -08:00
2014-05-26 14:09:26 -07:00
for ( GLint ii = 0 ; ii < numCmpFormats ; + + ii )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
GLint internalFmt = cmpFormat [ ii ] ;
uint32_t fmt = uint32_t ( TextureFormat : : Unknown ) ;
for ( uint32_t jj = 0 ; jj < fmt ; + + jj )
{
if ( s_textureFormat [ jj ] . m_internalFmt = = ( GLenum ) internalFmt )
{
s_textureFormat [ jj ] . m_supported = true ;
fmt = jj ;
}
}
2013-02-20 22:13:32 -08:00
2014-05-26 14:09:26 -07:00
BX_TRACE ( " %3d: %8x %s " , ii , internalFmt , getName ( ( TextureFormat : : Enum ) fmt ) ) ;
2012-07-08 19:10:07 -07:00
}
}
2014-05-26 14:09:26 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG ) )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
# define GL_GET(_pname, _min) BX_TRACE(" " #_pname " %d (min: %d)", glGet(_pname), _min)
BX_TRACE ( " Defaults: " ) ;
# if BGFX_CONFIG_RENDERER_OPENGL >= 41 || BGFX_CONFIG_RENDERER_OPENGLES
GL_GET ( GL_MAX_FRAGMENT_UNIFORM_VECTORS , 16 ) ;
GL_GET ( GL_MAX_VERTEX_UNIFORM_VECTORS , 128 ) ;
GL_GET ( GL_MAX_VARYING_VECTORS , 8 ) ;
# else
GL_GET ( GL_MAX_FRAGMENT_UNIFORM_COMPONENTS , 16 * 4 ) ;
GL_GET ( GL_MAX_VERTEX_UNIFORM_COMPONENTS , 128 * 4 ) ;
GL_GET ( GL_MAX_VARYING_FLOATS , 8 * 4 ) ;
# endif // BGFX_CONFIG_RENDERER_OPENGL >= 41 || BGFX_CONFIG_RENDERER_OPENGLES
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 ) ;
2015-08-09 07:53:48 -07:00
GL_GET ( GL_MAX_COLOR_ATTACHMENTS , 1 ) ;
GL_GET ( GL_MAX_DRAW_BUFFERS , 1 ) ;
2014-05-26 14:09:26 -07:00
# undef GL_GET
2012-07-08 19:10:07 -07:00
2014-05-26 14:09:26 -07:00
BX_TRACE ( " Vendor: %s " , m_vendor ) ;
BX_TRACE ( " Renderer: %s " , m_renderer ) ;
BX_TRACE ( " Version: %s " , m_version ) ;
BX_TRACE ( " GLSL version: %s " , m_glslVersion ) ;
2013-07-14 10:13:10 -07:00
}
2013-07-24 21:59:59 -07:00
2014-05-26 14:09:26 -07:00
// Initial binary shader hash depends on driver version.
m_hash = ( ( BX_PLATFORM_WINDOWS < < 1 ) | BX_ARCH_64BIT )
^ ( uint64_t ( getGLStringHash ( GL_VENDOR ) ) < < 32 )
^ ( uint64_t ( getGLStringHash ( GL_RENDERER ) ) < < 0 )
^ ( uint64_t ( getGLStringHash ( GL_VERSION ) ) < < 16 )
;
2013-07-24 21:59:59 -07:00
2015-08-28 11:17:26 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 )
& & 0 = = strcmp ( m_vendor , " Imagination Technologies " )
& & NULL ! = strstr ( m_version , " (SDK 3.5@3510720) " ) )
{
// Skip initializing extensions that are broken in emulator.
s_extension [ Extension : : ARB_program_interface_query ] . m_initialize =
s_extension [ Extension : : ARB_shader_storage_buffer_object ] . m_initialize = false ;
}
2014-05-26 14:09:26 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_USE_EXTENSIONS ) )
2013-07-24 21:59:59 -07:00
{
2014-05-26 14:09:26 -07:00
const char * extensions = ( const char * ) glGetString ( GL_EXTENSIONS ) ;
glGetError ( ) ; // ignore error if glGetString returns NULL.
if ( NULL ! = extensions )
2013-07-24 21:59:59 -07:00
{
2014-05-26 14:09:26 -07:00
char name [ 1024 ] ;
const char * pos = extensions ;
const char * end = extensions + strlen ( extensions ) ;
uint32_t index = 0 ;
while ( pos < end )
2013-07-24 21:59:59 -07:00
{
2014-05-26 14:09:26 -07:00
uint32_t len ;
const char * space = strchr ( pos , ' ' ) ;
if ( NULL ! = space )
{
len = bx : : uint32_min ( sizeof ( name ) , ( uint32_t ) ( space - pos ) ) ;
}
else
{
len = bx : : uint32_min ( sizeof ( name ) , ( uint32_t ) strlen ( pos ) ) ;
}
2014-02-20 23:03:31 -08:00
2014-05-26 14:09:26 -07:00
strncpy ( name , pos , len ) ;
name [ len ] = ' \0 ' ;
2014-02-20 23:03:31 -08:00
2016-01-05 21:06:42 -08:00
updateExtension ( name ) ;
2014-05-26 14:09:26 -07:00
pos + = len + 1 ;
+ + index ;
}
2016-01-05 21:06:42 -08:00
}
else if ( NULL ! = glGetStringi )
{
GLint numExtensions = 0 ;
glGetIntegerv ( GL_NUM_EXTENSIONS , & numExtensions ) ;
2016-01-10 23:00:34 -05:00
glGetError ( ) ; // ignore error if glGetIntegerv returns NULL.
2014-05-26 14:09:26 -07:00
2016-01-05 21:06:42 -08:00
for ( GLint index = 0 ; index < numExtensions ; + + index )
2014-05-26 14:09:26 -07:00
{
2016-01-05 21:06:42 -08:00
const char * name = ( const char * ) glGetStringi ( GL_EXTENSIONS , index ) ;
updateExtension ( name ) ;
}
}
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 ) ;
2013-07-24 21:59:59 -07:00
}
2014-02-20 23:03:31 -08:00
}
2014-05-26 14:09:26 -07:00
}
2015-03-28 21:25:40 -07:00
// Allow all texture filters.
memset ( s_textureFilter , true , BX_COUNTOF ( s_textureFilter ) ) ;
2014-05-26 14:09:26 -07:00
bool bc123Supported = 0
| | s_extension [ Extension : : EXT_texture_compression_s3tc ] . m_supported
| | s_extension [ Extension : : MOZ_WEBGL_compressed_texture_s3tc ] . m_supported
| | s_extension [ Extension : : WEBGL_compressed_texture_s3tc ] . m_supported
| | s_extension [ Extension : : WEBKIT_WEBGL_compressed_texture_s3tc ] . m_supported
;
s_textureFormat [ TextureFormat : : BC1 ] . m_supported | = bc123Supported
| | s_extension [ Extension : : ANGLE_texture_compression_dxt1 ] . m_supported
| | s_extension [ Extension : : EXT_texture_compression_dxt1 ] . m_supported
;
if ( ! s_textureFormat [ TextureFormat : : BC1 ] . m_supported
& & ( s_textureFormat [ TextureFormat : : BC2 ] . m_supported | | s_textureFormat [ TextureFormat : : BC3 ] . m_supported ) )
{
// If RGBA_S3TC_DXT1 is not supported, maybe RGB_S3TC_DXT1 is?
for ( GLint ii = 0 ; ii < numCmpFormats ; + + ii )
2014-02-20 23:03:31 -08:00
{
2014-05-26 14:09:26 -07:00
if ( GL_COMPRESSED_RGB_S3TC_DXT1_EXT = = cmpFormat [ ii ] )
{
setTextureFormat ( TextureFormat : : BC1 , GL_COMPRESSED_RGB_S3TC_DXT1_EXT , GL_COMPRESSED_RGB_S3TC_DXT1_EXT ) ;
s_textureFormat [ TextureFormat : : BC1 ] . m_supported = true ;
break ;
}
2014-02-20 23:03:31 -08:00
}
2013-07-24 21:59:59 -07:00
}
2013-01-12 19:13:51 -08:00
2014-05-26 14:09:26 -07:00
s_textureFormat [ TextureFormat : : BC2 ] . m_supported | = bc123Supported
| | s_extension [ Extension : : ANGLE_texture_compression_dxt3 ] . m_supported
| | s_extension [ Extension : : CHROMIUM_texture_compression_dxt3 ] . m_supported
;
s_textureFormat [ TextureFormat : : BC3 ] . m_supported | = bc123Supported
| | s_extension [ Extension : : ANGLE_texture_compression_dxt5 ] . m_supported
| | s_extension [ Extension : : CHROMIUM_texture_compression_dxt5 ] . m_supported
;
if ( s_extension [ Extension : : EXT_texture_compression_latc ] . m_supported )
2012-12-30 20:52:47 -08:00
{
2014-05-26 14:09:26 -07:00
setTextureFormat ( TextureFormat : : BC4 , GL_COMPRESSED_LUMINANCE_LATC1_EXT , GL_COMPRESSED_LUMINANCE_LATC1_EXT ) ;
setTextureFormat ( TextureFormat : : BC5 , GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT , GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT ) ;
2012-12-30 20:52:47 -08:00
}
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : ARB_texture_compression_rgtc ] . m_supported
| | s_extension [ Extension : : EXT_texture_compression_rgtc ] . m_supported )
2012-12-30 20:52:47 -08:00
{
2014-05-26 14:09:26 -07:00
setTextureFormat ( TextureFormat : : BC4 , GL_COMPRESSED_RED_RGTC1 , GL_COMPRESSED_RED_RGTC1 ) ;
setTextureFormat ( TextureFormat : : BC5 , GL_COMPRESSED_RG_RGTC2 , GL_COMPRESSED_RG_RGTC2 ) ;
2012-12-30 20:52:47 -08:00
}
2014-05-26 14:09:26 -07:00
bool etc1Supported = 0
| | s_extension [ Extension : : OES_compressed_ETC1_RGB8_texture ] . m_supported
| | s_extension [ Extension : : WEBGL_compressed_texture_etc1 ] . m_supported
;
s_textureFormat [ TextureFormat : : ETC1 ] . m_supported | = etc1Supported ;
2012-12-30 20:52:47 -08:00
2014-05-26 14:09:26 -07:00
bool etc2Supported = ! ! ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : ARB_ES3_compatibility ] . m_supported
;
s_textureFormat [ TextureFormat : : ETC2 ] . m_supported | = etc2Supported ;
s_textureFormat [ TextureFormat : : ETC2A ] . m_supported | = etc2Supported ;
s_textureFormat [ TextureFormat : : ETC2A1 ] . m_supported | = etc2Supported ;
2012-12-30 20:52:47 -08:00
2014-05-26 14:09:26 -07:00
if ( ! s_textureFormat [ TextureFormat : : ETC1 ] . m_supported
& & s_textureFormat [ TextureFormat : : ETC2 ] . m_supported )
2013-09-20 23:07:14 -07:00
{
2014-05-26 14:09:26 -07:00
// When ETC2 is supported override ETC1 texture format settings.
s_textureFormat [ TextureFormat : : ETC1 ] . m_internalFmt = GL_COMPRESSED_RGB8_ETC2 ;
s_textureFormat [ TextureFormat : : ETC1 ] . m_fmt = GL_COMPRESSED_RGB8_ETC2 ;
s_textureFormat [ TextureFormat : : ETC1 ] . m_supported = true ;
2013-09-20 23:07:14 -07:00
}
2012-12-30 20:52:47 -08:00
2014-05-26 14:09:26 -07:00
bool ptc1Supported = 0
| | s_extension [ Extension : : IMG_texture_compression_pvrtc ] . m_supported
| | s_extension [ Extension : : WEBGL_compressed_texture_pvrtc ] . m_supported
;
s_textureFormat [ TextureFormat : : PTC12 ] . m_supported | = ptc1Supported ;
s_textureFormat [ TextureFormat : : PTC14 ] . m_supported | = ptc1Supported ;
s_textureFormat [ TextureFormat : : PTC12A ] . m_supported | = ptc1Supported ;
s_textureFormat [ TextureFormat : : PTC14A ] . m_supported | = ptc1Supported ;
2012-12-30 20:52:47 -08:00
2014-05-26 14:09:26 -07:00
bool ptc2Supported = s_extension [ Extension : : IMG_texture_compression_pvrtc2 ] . m_supported ;
s_textureFormat [ TextureFormat : : PTC22 ] . m_supported | = ptc2Supported ;
s_textureFormat [ TextureFormat : : PTC24 ] . m_supported | = ptc2Supported ;
2012-07-08 19:10:07 -07:00
2014-05-26 14:09:26 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES ) )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
setTextureFormat ( TextureFormat : : D32 , GL_DEPTH_COMPONENT , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT ) ;
2015-03-04 22:08:54 -08:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES < 30 ) )
2014-05-26 14:09:26 -07:00
{
setTextureFormat ( TextureFormat : : RGBA16F , GL_RGBA , GL_RGBA , GL_HALF_FLOAT ) ;
2015-05-13 03:04:57 +08:00
// internalFormat and format must match:
// https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml
2015-05-12 17:25:09 -07:00
setTextureFormat ( TextureFormat : : RGBA8 , GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE ) ;
2016-01-11 14:49:56 -08:00
setTextureFormat ( TextureFormat : : R5G6B5 , GL_RGB , GL_RGB , GL_UNSIGNED_SHORT_5_6_5_REV ) ;
setTextureFormat ( TextureFormat : : RGBA4 , GL_RGBA , GL_RGBA , GL_UNSIGNED_SHORT_4_4_4_4_REV ) ;
setTextureFormat ( TextureFormat : : RGB5A1 , GL_RGBA , GL_RGBA , GL_UNSIGNED_SHORT_1_5_5_5_REV ) ;
2014-05-26 14:09:26 -07:00
2015-03-28 21:25:40 -07:00
if ( s_extension [ Extension : : OES_texture_half_float ] . m_supported
| | s_extension [ Extension : : OES_texture_float ] . m_supported )
{
// https://www.khronos.org/registry/gles/extensions/OES/OES_texture_float.txt
2015-03-28 22:03:25 -07:00
// When half/float is available via extensions texture will be marked as
2015-03-28 21:25:40 -07:00
// incomplete if it uses anything other than nearest filter.
2015-03-28 22:03:25 -07:00
const bool linear16F = s_extension [ Extension : : OES_texture_half_float_linear ] . m_supported ;
const bool linear32F = s_extension [ Extension : : OES_texture_float_linear ] . m_supported ;
s_textureFilter [ TextureFormat : : R16F ] = linear16F ;
s_textureFilter [ TextureFormat : : RG16F ] = linear16F ;
s_textureFilter [ TextureFormat : : RGBA16F ] = linear16F ;
s_textureFilter [ TextureFormat : : R32F ] = linear32F ;
s_textureFilter [ TextureFormat : : RG32F ] = linear32F ;
s_textureFilter [ TextureFormat : : RGBA32F ] = linear32F ;
2015-03-28 21:25:40 -07:00
}
2014-05-26 14:09:26 -07:00
if ( BX_ENABLED ( BX_PLATFORM_IOS ) )
{
setTextureFormat ( TextureFormat : : D16 , GL_DEPTH_COMPONENT , GL_DEPTH_COMPONENT , GL_UNSIGNED_SHORT ) ;
setTextureFormat ( TextureFormat : : D24S8 , GL_DEPTH_STENCIL , GL_DEPTH_STENCIL , GL_UNSIGNED_INT_24_8 ) ;
}
}
2012-07-08 19:10:07 -07:00
}
2015-03-04 22:08:54 -08:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
{
2016-02-21 20:35:40 +10:00
setTextureFormat ( TextureFormat : : R8I , GL_R8I , GL_RED_INTEGER , GL_BYTE ) ;
setTextureFormat ( TextureFormat : : R8U , GL_R8UI , GL_RED_INTEGER , GL_UNSIGNED_BYTE ) ;
2015-08-28 17:41:24 -07:00
setTextureFormat ( TextureFormat : : R16I , GL_R16I , GL_RED_INTEGER , GL_SHORT ) ;
2015-08-28 14:48:51 -07:00
setTextureFormat ( TextureFormat : : R16U , GL_R16UI , GL_RED_INTEGER , GL_UNSIGNED_SHORT ) ;
2015-08-28 17:41:24 -07:00
// setTextureFormat(TextureFormat::RG16, GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT);
// setTextureFormat(TextureFormat::RGBA16, GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT);
2015-08-28 14:48:51 -07:00
setTextureFormat ( TextureFormat : : R32U , GL_R32UI , GL_RED_INTEGER , GL_UNSIGNED_INT ) ;
setTextureFormat ( TextureFormat : : RG32U , GL_RG32UI , GL_RG_INTEGER , GL_UNSIGNED_INT ) ;
setTextureFormat ( TextureFormat : : RGBA32U , GL_RGBA32UI , GL_RGBA_INTEGER , GL_UNSIGNED_INT ) ;
2015-03-04 22:08:54 -08:00
}
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : EXT_texture_format_BGRA8888 ] . m_supported
| | s_extension [ Extension : : EXT_bgra ] . m_supported
| | s_extension [ Extension : : IMG_texture_format_BGRA8888 ] . m_supported
| | s_extension [ Extension : : APPLE_texture_format_BGRA8888 ] . m_supported )
{
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
{
m_readPixelsFmt = GL_BGRA ;
}
2012-07-08 19:10:07 -07:00
2014-05-26 14:09:26 -07:00
// Mixing GLES and GL extensions here. OpenGL EXT_bgra and
// APPLE_texture_format_BGRA8888 wants
// format to be BGRA but internal format to stay RGBA, but
// EXT_texture_format_BGRA8888 wants both format and internal
// format to be BGRA.
//
// Reference:
// https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_format_BGRA8888.txt
// https://www.opengl.org/registry/specs/EXT/bgra.txt
// https://www.khronos.org/registry/gles/extensions/APPLE/APPLE_texture_format_BGRA8888.txt
if ( ! s_extension [ Extension : : EXT_bgra ] . m_supported
& & ! s_extension [ Extension : : APPLE_texture_format_BGRA8888 ] . m_supported )
{
s_textureFormat [ TextureFormat : : BGRA8 ] . m_internalFmt = GL_BGRA ;
}
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
if ( ! isTextureFormatValid ( TextureFormat : : BGRA8 ) )
{
// Revert back to RGBA if texture can't be created.
2015-04-11 09:42:17 -07:00
setTextureFormat ( TextureFormat : : BGRA8 , GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE ) ;
2014-05-26 14:09:26 -07:00
}
}
2014-05-10 20:51:44 -07:00
2015-02-20 15:35:20 -08:00
if ( BX_ENABLED ( BX_PLATFORM_EMSCRIPTEN )
| | ! isTextureFormatValid ( TextureFormat : : R8 ) )
2015-01-08 20:43:36 -08:00
{
// GL core has to use GL_R8 Issue#208, GLES2 has to use GL_LUMINANCE issue#226
s_textureFormat [ TextureFormat : : R8 ] . m_internalFmt = GL_LUMINANCE ;
s_textureFormat [ TextureFormat : : R8 ] . m_fmt = GL_LUMINANCE ;
}
2015-10-08 17:34:03 -07:00
for ( uint32_t ii = BX_ENABLED ( BX_PLATFORM_IOS ) ? TextureFormat : : Unknown : 0 // skip test on iOS!
; ii < TextureFormat : : Count
; + + ii
)
2014-05-26 14:09:26 -07:00
{
2015-05-12 23:03:17 -07:00
if ( TextureFormat : : Unknown ! = ii
& & TextureFormat : : UnknownDepth ! = ii )
2014-05-10 20:51:44 -07:00
{
2015-05-12 23:03:17 -07:00
s_textureFormat [ ii ] . m_supported = isTextureFormatValid ( TextureFormat : : Enum ( ii ) ) ;
2014-05-26 14:09:26 -07:00
}
}
2014-05-10 20:51:44 -07:00
2015-04-26 15:23:33 -07:00
if ( BX_ENABLED ( 0 ) )
{
// Disable all compressed texture formats. For testing only.
for ( uint32_t ii = 0 ; ii < TextureFormat : : Unknown ; + + ii )
{
s_textureFormat [ ii ] . m_supported = false ;
}
}
2015-04-21 15:44:16 -07:00
const bool computeSupport = false
| | ! ! ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 )
| | s_extension [ Extension : : ARB_compute_shader ] . m_supported
;
2014-07-27 20:44:02 -07:00
for ( uint32_t ii = 0 ; ii < TextureFormat : : Count ; + + ii )
{
2015-04-21 15:44:16 -07:00
uint8_t supported = 0 ;
supported | = s_textureFormat [ ii ] . m_supported
2015-10-23 12:57:04 -07:00
? BGFX_CAPS_FORMAT_TEXTURE_2D
2015-10-23 14:21:54 -07:00
| BGFX_CAPS_FORMAT_TEXTURE_3D
| BGFX_CAPS_FORMAT_TEXTURE_CUBE
2015-04-21 15:44:16 -07:00
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
2015-05-12 23:03:17 -07:00
supported | = isTextureFormatValid ( TextureFormat : : Enum ( ii ) , true )
2015-10-23 12:57:04 -07:00
? BGFX_CAPS_FORMAT_TEXTURE_2D_SRGB
2015-10-23 14:21:54 -07:00
| BGFX_CAPS_FORMAT_TEXTURE_3D_SRGB
| BGFX_CAPS_FORMAT_TEXTURE_CUBE_SRGB
2015-05-04 20:57:22 -07:00
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
2015-04-21 15:44:16 -07:00
supported | = computeSupport
2015-05-18 14:35:05 -07:00
& & isImageFormatValid ( TextureFormat : : Enum ( ii ) )
2015-04-21 15:44:16 -07:00
? BGFX_CAPS_FORMAT_TEXTURE_IMAGE
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
2015-05-18 12:39:42 -07:00
supported | = isFramebufferFormatValid ( TextureFormat : : Enum ( ii ) )
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
2015-09-01 13:23:20 -07:00
if ( NULL ! = glGetInternalformativ )
{
GLint maxSamples ;
2015-09-01 13:34:36 -07:00
glGetInternalformativ ( GL_RENDERBUFFER
2015-09-01 13:23:20 -07:00
, s_textureFormat [ ii ] . m_internalFmt
, GL_SAMPLES
, 1
, & maxSamples
2015-09-01 13:34:36 -07:00
) ;
GLenum err = glGetError ( ) ;
supported | = 0 = = err & & maxSamples > 0
2015-09-01 13:23:20 -07:00
? BGFX_CAPS_FORMAT_TEXTURE_FRAMEBUFFER_MSAA
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
2015-09-01 13:34:36 -07:00
glGetInternalformativ ( GL_TEXTURE_2D_MULTISAMPLE
2015-09-01 13:23:20 -07:00
, s_textureFormat [ ii ] . m_internalFmt
, GL_SAMPLES
, 1
, & maxSamples
2015-09-01 13:34:36 -07:00
) ;
err = glGetError ( ) ;
supported | = 0 = = err & & maxSamples > 0
2015-09-01 13:23:20 -07:00
? BGFX_CAPS_FORMAT_TEXTURE_MSAA
: BGFX_CAPS_FORMAT_TEXTURE_NONE
;
}
2015-04-21 15:44:16 -07:00
g_caps . formats [ ii ] = supported ;
2014-07-27 20:44:02 -07:00
}
2014-05-10 20:51:44 -07:00
2015-04-08 19:59:48 -07:00
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : OES_texture_3D ] . m_supported
2014-05-26 14:09:26 -07:00
? BGFX_CAPS_TEXTURE_3D
: 0
;
2015-04-08 19:59:48 -07:00
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : EXT_shadow_samplers ] . m_supported
2014-05-26 14:09:26 -07:00
? BGFX_CAPS_TEXTURE_COMPARE_ALL
: 0
;
2015-04-08 19:59:48 -07:00
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : OES_vertex_half_float ] . m_supported
2014-05-26 14:09:26 -07:00
? BGFX_CAPS_VERTEX_ATTRIB_HALF
: 0
;
2015-08-04 19:03:56 -07:00
g_caps . supported | = false
| | s_extension [ Extension : : ARB_vertex_type_2_10_10_10_rev ] . m_supported
| | s_extension [ Extension : : OES_vertex_type_10_10_10_2 ] . m_supported
? BGFX_CAPS_VERTEX_ATTRIB_UINT10
: 0
;
2015-04-08 19:59:48 -07:00
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : EXT_frag_depth ] . m_supported
2014-05-26 14:09:26 -07:00
? BGFX_CAPS_FRAGMENT_DEPTH
: 0
;
g_caps . supported | = s_extension [ Extension : : ARB_draw_buffers_blend ] . m_supported
? BGFX_CAPS_BLEND_INDEPENDENT
: 0
;
2014-07-29 21:29:38 -07:00
g_caps . supported | = s_extension [ Extension : : INTEL_fragment_shader_ordering ] . m_supported
? BGFX_CAPS_FRAGMENT_ORDERING
: 0
;
2015-04-08 19:59:48 -07:00
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : OES_element_index_uint ] . m_supported
? BGFX_CAPS_INDEX32
: 0
;
2014-07-29 21:29:38 -07:00
2015-04-29 23:20:21 -07:00
const bool drawIndirectSupported = false
| | s_extension [ Extension : : AMD_multi_draw_indirect ] . m_supported
| | s_extension [ Extension : : ARB_draw_indirect ] . m_supported
| | s_extension [ Extension : : ARB_multi_draw_indirect ] . m_supported
| | s_extension [ Extension : : EXT_multi_draw_indirect ] . m_supported
;
2015-04-30 18:06:41 -07:00
if ( drawIndirectSupported )
{
if ( NULL = = glMultiDrawArraysIndirect
| | NULL = = glMultiDrawElementsIndirect )
{
glMultiDrawArraysIndirect = stubMultiDrawArraysIndirect ;
glMultiDrawElementsIndirect = stubMultiDrawElementsIndirect ;
}
}
2015-04-29 23:20:21 -07:00
g_caps . supported | = drawIndirectSupported
2015-04-30 18:06:41 -07:00
? BGFX_CAPS_DRAW_INDIRECT
2015-04-29 23:20:21 -07:00
: 0
;
2015-10-16 17:42:40 -07:00
if ( s_extension [ Extension : : ARB_copy_image ] . m_supported
| | s_extension [ Extension : : EXT_copy_image ] . m_supported
| | s_extension [ Extension : : NV_copy_image ] . m_supported
| | s_extension [ Extension : : OES_copy_image ] . m_supported )
{
m_blitSupported = NULL ! = glCopyImageSubData ;
g_caps . supported | = m_blitSupported
2015-10-20 16:32:08 -07:00
? BGFX_CAPS_TEXTURE_BLIT
2015-10-16 17:42:40 -07:00
: 0
;
}
2015-10-20 19:57:44 -07:00
g_caps . supported | = m_readBackSupported
? BGFX_CAPS_TEXTURE_READ_BACK
: 0
;
2015-04-07 17:58:14 -07:00
g_caps . maxTextureSize = uint16_t ( glGet ( GL_MAX_TEXTURE_SIZE ) ) ;
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
2014-09-12 00:02:12 -07:00
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
2015-03-22 22:03:37 -07:00
| | s_extension [ Extension : : EXT_draw_buffers ] . m_supported
| | s_extension [ Extension : : WEBGL_draw_buffers ] . m_supported )
2014-05-26 14:09:26 -07:00
{
2015-08-09 07:53:48 -07:00
g_caps . maxFBAttachments = uint8_t ( bx : : uint32_min ( glGet ( GL_MAX_DRAW_BUFFERS )
, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS )
) ;
2014-05-10 20:51:44 -07:00
}
2014-05-26 14:09:26 -07:00
m_vaoSupport = ! ! ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : ARB_vertex_array_object ] . m_supported
| | s_extension [ Extension : : OES_vertex_array_object ] . m_supported
;
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
if ( BX_ENABLED ( BX_PLATFORM_NACL ) )
{
2015-03-30 08:58:15 -07:00
m_vaoSupport & = true
& & NULL ! = glGenVertexArrays
2014-05-26 14:09:26 -07:00
& & NULL ! = glDeleteVertexArrays
& & NULL ! = glBindVertexArray
;
}
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
if ( m_vaoSupport )
2014-05-10 20:51:44 -07:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glGenVertexArrays ( 1 , & m_vao ) ) ;
}
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
m_samplerObjectSupport = ! ! ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : ARB_sampler_objects ] . m_supported
;
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
m_shadowSamplersSupport = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : EXT_shadow_samplers ] . m_supported
;
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
m_programBinarySupport = ! ! ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : ARB_get_program_binary ] . m_supported
| | s_extension [ Extension : : OES_get_program_binary ] . m_supported
| | s_extension [ Extension : : IMG_shader_binary ] . m_supported
;
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
m_textureSwizzleSupport = false
| | s_extension [ Extension : : ARB_texture_swizzle ] . m_supported
| | s_extension [ Extension : : EXT_texture_swizzle ] . m_supported
;
2013-01-13 18:39:25 -08:00
2014-05-26 14:09:26 -07:00
m_depthTextureSupport = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
| | s_extension [ Extension : : ANGLE_depth_texture ] . m_supported
| | s_extension [ Extension : : CHROMIUM_depth_texture ] . m_supported
| | s_extension [ Extension : : GOOGLE_depth_texture ] . m_supported
| | s_extension [ Extension : : OES_depth_texture ] . m_supported
| | s_extension [ Extension : : MOZ_WEBGL_depth_texture ] . m_supported
| | s_extension [ Extension : : WEBGL_depth_texture ] . m_supported
| | s_extension [ Extension : : WEBKIT_WEBGL_depth_texture ] . m_supported
;
2013-04-20 23:13:44 -07:00
2015-08-16 21:31:04 -07:00
m_timerQuerySupport = false
2015-03-30 00:06:34 -07:00
| | s_extension [ Extension : : ANGLE_timer_query ] . m_supported
| | s_extension [ Extension : : ARB_timer_query ] . m_supported
| | s_extension [ Extension : : EXT_disjoint_timer_query ] . m_supported
| | s_extension [ Extension : : EXT_timer_query ] . m_supported
;
2015-08-16 21:31:04 -07:00
m_timerQuerySupport & = true
2015-12-08 20:34:31 -08:00
& & NULL ! = glQueryCounter
2015-08-16 21:31:04 -07:00
& & NULL ! = glGetQueryObjectiv
& & NULL ! = glGetQueryObjectui64v
;
2015-03-30 08:58:15 -07:00
2015-11-01 19:12:42 -08:00
m_occlusionQuerySupport = false
| | s_extension [ Extension : : ARB_occlusion_query ] . m_supported
| | s_extension [ Extension : : ARB_occlusion_query2 ] . m_supported
| | s_extension [ Extension : : EXT_occlusion_query_boolean ] . m_supported
| | s_extension [ Extension : : NV_occlusion_query ] . m_supported
;
2015-11-16 21:31:27 -08:00
m_occlusionQuerySupport & = true
& & NULL ! = glGenQueries
& & NULL ! = glDeleteQueries
& & NULL ! = glBeginQuery
& & NULL ! = glEndQuery
;
2016-03-16 20:04:06 -07:00
m_atocSupport = s_extension [ Extension : : ARB_multisample ] . m_supported ;
m_conservativeRasterSupport = s_extension [ Extension : : NV_conservative_raster ] . m_supported ;
2015-11-01 19:12:42 -08:00
2016-03-16 20:04:06 -07:00
g_caps . supported | = 0
| ( m_atocSupport ? BGFX_CAPS_ALPHA_TO_COVERAGE : 0 )
| ( m_conservativeRasterSupport ? BGFX_CAPS_CONSERVATIVE_RASTER : 0 )
| ( m_occlusionQuerySupport ? BGFX_CAPS_OCCLUSION_QUERY : 0 )
| ( m_depthTextureSupport ? BGFX_CAPS_TEXTURE_COMPARE_LEQUAL : 0 )
| ( computeSupport ? BGFX_CAPS_COMPUTE : 0 )
2014-07-20 20:27:13 -07:00
;
2015-08-17 18:07:00 -07:00
g_caps . supported | = m_glctx . getCaps ( ) ;
2014-09-23 20:35:39 -07:00
2015-09-11 20:05:13 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES ) )
{
2015-11-30 14:50:28 -08:00
m_srgbWriteControlSupport = s_extension [ Extension : : EXT_sRGB_write_control ] . m_supported ;
2015-09-12 09:25:37 -07:00
m_borderColorSupport = s_extension [ Extension : : NV_texture_border_clamp ] . m_supported ;
2015-09-11 20:05:13 -07:00
s_textureAddress [ BGFX_TEXTURE_U_BORDER > > BGFX_TEXTURE_U_SHIFT ] = s_extension [ Extension : : NV_texture_border_clamp ] . m_supported
? GL_CLAMP_TO_BORDER
: GL_CLAMP_TO_EDGE
;
}
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : EXT_texture_filter_anisotropic ] . m_supported )
{
2015-01-21 20:39:42 -08:00
GL_CHECK ( glGetFloatv ( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT , & m_maxAnisotropyDefault ) ) ;
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : ARB_texture_multisample ] . m_supported
| | s_extension [ Extension : : ANGLE_framebuffer_multisample ] . m_supported )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glGetIntegerv ( GL_MAX_SAMPLES , & m_maxMsaa ) ) ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : OES_read_format ] . m_supported
& & ( s_extension [ Extension : : IMG_read_format ] . m_supported | | s_extension [ Extension : : EXT_read_format_bgra ] . m_supported ) )
{
m_readPixelsFmt = GL_BGRA ;
}
else
{
m_readPixelsFmt = GL_RGBA ;
}
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
{
g_caps . supported | = BGFX_CAPS_INSTANCING ;
}
else
{
2016-03-10 23:41:33 -08:00
if ( s_extension [ Extension : : ANGLE_instanced_arrays ] . m_supported
| | s_extension [ Extension : : ARB_instanced_arrays ] . m_supported
| | s_extension [ Extension : : EXT_instanced_arrays ] . m_supported )
2014-03-04 22:20:37 -08:00
{
2016-03-10 23:41:33 -08:00
if ( NULL ! = glVertexAttribDivisor
& & NULL ! = glDrawArraysInstanced
& & NULL ! = glDrawElementsInstanced )
2014-03-04 22:20:37 -08:00
{
2016-03-10 23:41:33 -08:00
g_caps . supported | = BGFX_CAPS_INSTANCING ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
if ( 0 = = ( g_caps . supported & BGFX_CAPS_INSTANCING ) )
{
glVertexAttribDivisor = stubVertexAttribDivisor ;
glDrawArraysInstanced = stubDrawArraysInstanced ;
glDrawElementsInstanced = stubDrawElementsInstanced ;
2014-03-04 22:20:37 -08:00
}
}
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : ARB_debug_output ] . m_supported
| | s_extension [ Extension : : KHR_debug ] . m_supported )
{
2015-04-22 15:11:45 -07:00
if ( NULL ! = glDebugMessageControl
& & NULL ! = glDebugMessageInsert
& & NULL ! = glDebugMessageCallback
& & NULL ! = glGetDebugMessageLog )
{
GL_CHECK ( glDebugMessageCallback ( debugProcCb , NULL ) ) ;
GL_CHECK ( glDebugMessageControl ( GL_DONT_CARE
, GL_DONT_CARE
, GL_DEBUG_SEVERITY_MEDIUM
, 0
, NULL
, GL_TRUE
) ) ;
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : ARB_seamless_cube_map ] . m_supported )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glEnable ( GL_TEXTURE_CUBE_MAP_SEAMLESS ) ) ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
if ( NULL = = glFrameTerminatorGREMEDY
| | ! s_extension [ Extension : : GREMEDY_frame_terminator ] . m_supported )
{
glFrameTerminatorGREMEDY = stubFrameTerminatorGREMEDY ;
}
2014-03-16 17:43:51 -07:00
2014-05-26 14:09:26 -07:00
if ( NULL = = glInsertEventMarker
| | ! s_extension [ Extension : : EXT_debug_marker ] . m_supported )
{
glInsertEventMarker = ( NULL ! = glStringMarkerGREMEDY & & s_extension [ Extension : : GREMEDY_string_marker ] . m_supported )
? stubInsertEventMarkerGREMEDY
: stubInsertEventMarker
;
}
2014-03-04 22:20:37 -08:00
2015-05-08 11:49:18 -07:00
setGraphicsDebuggerPresent ( s_extension [ Extension : : EXT_debug_tool ] . m_supported ) ;
2014-05-26 14:09:26 -07:00
if ( NULL = = glObjectLabel )
{
glObjectLabel = stubObjectLabel ;
}
2014-03-04 22:20:37 -08:00
2015-01-11 18:00:08 -08:00
if ( NULL = = glInvalidateFramebuffer )
{
glInvalidateFramebuffer = stubInvalidateFramebuffer ;
}
2015-11-01 19:12:42 -08:00
if ( m_timerQuerySupport )
2014-05-26 14:09:26 -07:00
{
2015-08-16 15:37:46 -07:00
m_gpuTimer . create ( ) ;
2014-05-26 14:09:26 -07:00
}
2014-10-25 18:07:51 -07:00
2015-11-01 19:12:42 -08:00
if ( m_occlusionQuerySupport )
{
m_occlusionQuery . create ( ) ;
}
2014-10-25 18:07:51 -07:00
// Init reserved part of view name.
2015-02-21 15:51:03 -08:00
for ( uint32_t ii = 0 ; ii < BGFX_CONFIG_MAX_VIEWS ; + + ii )
2014-10-25 18:07:51 -07:00
{
2015-04-02 11:57:53 -07:00
bx : : snprintf ( s_viewName [ ii ] , BGFX_CONFIG_MAX_VIEW_NAME_RESERVED + 1 , " %3d " , ii ) ;
2014-10-25 18:07:51 -07:00
}
2014-10-28 22:08:55 -07:00
ovrPostReset ( ) ;
2015-11-16 10:42:56 -04:00
BGFX_GPU_PROFILER_BIND ( ) ;
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-10-13 21:14:51 -07:00
void shutdown ( )
2014-05-26 14:09:26 -07:00
{
2015-11-16 10:42:56 -04:00
BGFX_GPU_PROFILER_UNBIND ( ) ;
2014-10-28 22:08:55 -07:00
ovrPreReset ( ) ;
m_ovr . shutdown ( ) ;
2014-05-26 14:09:26 -07:00
if ( m_vaoSupport )
{
GL_CHECK ( glBindVertexArray ( 0 ) ) ;
GL_CHECK ( glDeleteVertexArrays ( 1 , & m_vao ) ) ;
m_vao = 0 ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
captureFinish ( ) ;
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
invalidateCache ( ) ;
2015-11-01 19:12:42 -08:00
if ( m_timerQuerySupport )
2014-03-04 22:20:37 -08:00
{
2015-08-16 15:37:46 -07:00
m_gpuTimer . destroy ( ) ;
2014-03-04 22:20:37 -08:00
}
2015-11-01 19:12:42 -08:00
if ( m_occlusionQuerySupport )
{
m_occlusionQuery . destroy ( ) ;
}
2014-05-26 14:09:26 -07:00
destroyMsaaFbo ( ) ;
m_glctx . destroy ( ) ;
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
m_flip = false ;
2014-12-11 20:48:16 -08:00
unloadRenderDoc ( m_renderdocdll ) ;
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
RendererType : : Enum getRendererType ( ) const BX_OVERRIDE
{
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
2014-04-02 22:06:18 -07:00
{
2014-05-26 14:09:26 -07:00
return RendererType : : OpenGL ;
2014-04-02 22:06:18 -07:00
}
2014-05-26 14:09:26 -07:00
return RendererType : : OpenGLES ;
}
const char * getRendererName ( ) const BX_OVERRIDE
{
return BGFX_RENDERER_OPENGL_NAME ;
}
2015-04-15 20:59:00 -07:00
void flip ( HMD & _hmd )
2014-05-26 14:09:26 -07:00
{
if ( m_flip )
2014-04-02 20:52:15 -07:00
{
2014-09-07 17:17:38 -07:00
for ( uint32_t ii = 1 , num = m_numWindows ; ii < num ; + + ii )
{
m_glctx . swap ( m_frameBuffers [ m_windows [ ii ] . idx ] . m_swapChain ) ;
}
2014-10-28 22:08:55 -07:00
2015-04-15 20:59:00 -07:00
if ( ! m_ovr . swap ( _hmd ) )
2014-10-28 22:08:55 -07:00
{
m_glctx . swap ( ) ;
}
2014-04-02 20:52:15 -07:00
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2015-05-14 11:37:32 -07:00
void createIndexBuffer ( IndexBufferHandle _handle , Memory * _mem , uint16_t _flags ) BX_OVERRIDE
2014-05-26 14:09:26 -07:00
{
2015-04-08 19:59:48 -07:00
m_indexBuffers [ _handle . idx ] . create ( _mem - > size , _mem - > data , _flags ) ;
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void destroyIndexBuffer ( IndexBufferHandle _handle ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . destroy ( ) ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void createVertexDecl ( VertexDeclHandle _handle , const VertexDecl & _decl ) BX_OVERRIDE
{
VertexDecl & decl = m_vertexDecls [ _handle . idx ] ;
memcpy ( & decl , & _decl , sizeof ( VertexDecl ) ) ;
dump ( decl ) ;
}
void destroyVertexDecl ( VertexDeclHandle /*_handle*/ ) BX_OVERRIDE
{
}
2015-05-14 11:37:32 -07:00
void createVertexBuffer ( VertexBufferHandle _handle , Memory * _mem , VertexDeclHandle _declHandle , uint16_t _flags ) BX_OVERRIDE
2014-05-26 14:09:26 -07:00
{
2015-04-30 18:06:41 -07:00
m_vertexBuffers [ _handle . idx ] . create ( _mem - > size , _mem - > data , _declHandle , _flags ) ;
2014-05-26 14:09:26 -07:00
}
void destroyVertexBuffer ( VertexBufferHandle _handle ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . destroy ( ) ;
}
2015-05-14 11:37:32 -07:00
void createDynamicIndexBuffer ( IndexBufferHandle _handle , uint32_t _size , uint16_t _flags ) BX_OVERRIDE
2014-05-26 14:09:26 -07:00
{
2015-04-08 19:59:48 -07:00
m_indexBuffers [ _handle . idx ] . create ( _size , NULL , _flags ) ;
2014-05-26 14:09:26 -07:00
}
void updateDynamicIndexBuffer ( IndexBufferHandle _handle , uint32_t _offset , uint32_t _size , Memory * _mem ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . update ( _offset , bx : : uint32_min ( _size , _mem - > size ) , _mem - > data ) ;
}
void destroyDynamicIndexBuffer ( IndexBufferHandle _handle ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . destroy ( ) ;
}
2015-05-14 11:37:32 -07:00
void createDynamicVertexBuffer ( VertexBufferHandle _handle , uint32_t _size , uint16_t _flags ) BX_OVERRIDE
2014-05-26 14:09:26 -07:00
{
VertexDeclHandle decl = BGFX_INVALID_HANDLE ;
2015-04-30 18:06:41 -07:00
m_vertexBuffers [ _handle . idx ] . create ( _size , NULL , decl , _flags ) ;
2014-05-26 14:09:26 -07:00
}
void updateDynamicVertexBuffer ( VertexBufferHandle _handle , uint32_t _offset , uint32_t _size , Memory * _mem ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . update ( _offset , bx : : uint32_min ( _size , _mem - > size ) , _mem - > data ) ;
}
void destroyDynamicVertexBuffer ( VertexBufferHandle _handle ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . destroy ( ) ;
}
void createShader ( ShaderHandle _handle , Memory * _mem ) BX_OVERRIDE
{
m_shaders [ _handle . idx ] . create ( _mem ) ;
}
void destroyShader ( ShaderHandle _handle ) BX_OVERRIDE
{
m_shaders [ _handle . idx ] . destroy ( ) ;
}
void createProgram ( ProgramHandle _handle , ShaderHandle _vsh , ShaderHandle _fsh ) BX_OVERRIDE
{
ShaderGL dummyFragmentShader ;
m_program [ _handle . idx ] . create ( m_shaders [ _vsh . idx ] , isValid ( _fsh ) ? m_shaders [ _fsh . idx ] : dummyFragmentShader ) ;
}
void destroyProgram ( ProgramHandle _handle ) BX_OVERRIDE
{
m_program [ _handle . idx ] . destroy ( ) ;
}
void createTexture ( TextureHandle _handle , Memory * _mem , uint32_t _flags , uint8_t _skip ) BX_OVERRIDE
{
m_textures [ _handle . idx ] . create ( _mem , _flags , _skip ) ;
}
void updateTextureBegin ( TextureHandle /*_handle*/ , uint8_t /*_side*/ , uint8_t /*_mip*/ ) BX_OVERRIDE
{
}
void updateTexture ( TextureHandle _handle , uint8_t _side , uint8_t _mip , const Rect & _rect , uint16_t _z , uint16_t _depth , uint16_t _pitch , const Memory * _mem ) BX_OVERRIDE
{
m_textures [ _handle . idx ] . update ( _side , _mip , _rect , _z , _depth , _pitch , _mem ) ;
}
void updateTextureEnd ( ) BX_OVERRIDE
{
}
2015-10-20 16:32:08 -07:00
void readTexture ( TextureHandle _handle , void * _data ) BX_OVERRIDE
{
if ( m_readBackSupported )
{
const TextureGL & texture = m_textures [ _handle . idx ] ;
const bool compressed = isCompressed ( TextureFormat : : Enum ( texture . m_textureFormat ) ) ;
GL_CHECK ( glBindTexture ( texture . m_target , texture . m_id ) ) ;
if ( compressed )
{
GL_CHECK ( glGetCompressedTexImage ( texture . m_target
, 0
, _data
) ) ;
}
else
{
GL_CHECK ( glGetTexImage ( texture . m_target
, 0
, texture . m_fmt
, texture . m_type
, _data
) ) ;
}
GL_CHECK ( glBindTexture ( texture . m_target , 0 ) ) ;
}
}
2015-04-13 18:39:38 -07:00
void resizeTexture ( TextureHandle _handle , uint16_t _width , uint16_t _height ) BX_OVERRIDE
{
TextureGL & texture = m_textures [ _handle . idx ] ;
uint32_t size = sizeof ( uint32_t ) + sizeof ( TextureCreate ) ;
const Memory * mem = alloc ( size ) ;
bx : : StaticMemoryBlockWriter writer ( mem - > data , mem - > size ) ;
uint32_t magic = BGFX_CHUNK_MAGIC_TEX ;
bx : : write ( & writer , magic ) ;
TextureCreate tc ;
tc . m_width = _width ;
tc . m_height = _height ;
tc . m_sides = 0 ;
tc . m_depth = 0 ;
tc . m_numMips = 1 ;
2016-01-04 21:48:01 -08:00
tc . m_format = TextureFormat : : Enum ( texture . m_requestedFormat ) ;
2015-04-13 18:39:38 -07:00
tc . m_cubeMap = false ;
tc . m_mem = NULL ;
bx : : write ( & writer , tc ) ;
texture . destroy ( ) ;
2016-03-13 12:13:19 -07:00
texture . create ( mem , texture . m_flags , 0 ) ;
2015-04-13 18:39:38 -07:00
release ( mem ) ;
}
2016-01-20 19:27:48 -08:00
void overrideInternal ( TextureHandle _handle , uintptr_t _ptr ) BX_OVERRIDE
2016-01-17 20:33:39 -08:00
{
2016-01-27 14:50:57 -08:00
m_textures [ _handle . idx ] . overrideInternal ( _ptr ) ;
2016-01-17 20:33:39 -08:00
}
2016-01-18 17:29:53 -08:00
uintptr_t getInternal ( TextureHandle _handle ) BX_OVERRIDE
{
return uintptr_t ( m_textures [ _handle . idx ] . m_id ) ;
}
2014-05-26 14:09:26 -07:00
void destroyTexture ( TextureHandle _handle ) BX_OVERRIDE
{
m_textures [ _handle . idx ] . destroy ( ) ;
}
2016-02-15 16:55:32 -08:00
void createFrameBuffer ( FrameBufferHandle _handle , uint8_t _num , const Attachment * _attachment ) BX_OVERRIDE
2014-05-26 14:09:26 -07:00
{
2016-02-15 16:55:32 -08:00
m_frameBuffers [ _handle . idx ] . create ( _num , _attachment ) ;
2014-05-26 14:09:26 -07:00
}
2014-09-07 17:17:38 -07:00
void createFrameBuffer ( FrameBufferHandle _handle , void * _nwh , uint32_t _width , uint32_t _height , TextureFormat : : Enum _depthFormat ) BX_OVERRIDE
{
uint16_t denseIdx = m_numWindows + + ;
m_windows [ denseIdx ] = _handle ;
m_frameBuffers [ _handle . idx ] . create ( denseIdx , _nwh , _width , _height , _depthFormat ) ;
}
2014-05-26 14:09:26 -07:00
void destroyFrameBuffer ( FrameBufferHandle _handle ) BX_OVERRIDE
{
2014-09-07 17:17:38 -07:00
uint16_t denseIdx = m_frameBuffers [ _handle . idx ] . destroy ( ) ;
if ( UINT16_MAX ! = denseIdx )
{
- - m_numWindows ;
if ( m_numWindows > 1 )
{
FrameBufferHandle handle = m_windows [ m_numWindows ] ;
m_windows [ denseIdx ] = handle ;
m_frameBuffers [ handle . idx ] . m_denseIdx = denseIdx ;
}
}
2014-05-26 14:09:26 -07:00
}
void createUniform ( UniformHandle _handle , UniformType : : Enum _type , uint16_t _num , const char * _name ) BX_OVERRIDE
{
if ( NULL ! = m_uniforms [ _handle . idx ] )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
BX_FREE ( g_allocator , m_uniforms [ _handle . idx ] ) ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
uint32_t size = g_uniformTypeSize [ _type ] * _num ;
void * data = BX_ALLOC ( g_allocator , size ) ;
memset ( data , 0 , size ) ;
m_uniforms [ _handle . idx ] = data ;
m_uniformReg . add ( _handle , _name , m_uniforms [ _handle . idx ] ) ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void destroyUniform ( UniformHandle _handle ) BX_OVERRIDE
{
BX_FREE ( g_allocator , m_uniforms [ _handle . idx ] ) ;
m_uniforms [ _handle . idx ] = NULL ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void saveScreenShot ( const char * _filePath ) BX_OVERRIDE
{
uint32_t length = m_resolution . m_width * m_resolution . m_height * 4 ;
uint8_t * data = ( uint8_t * ) BX_ALLOC ( g_allocator , length ) ;
2014-04-12 21:25:38 -07:00
2014-10-28 22:08:55 -07:00
uint32_t width = m_resolution . m_width ;
2014-05-26 14:09:26 -07:00
uint32_t height = m_resolution . m_height ;
2014-04-15 22:59:40 -07:00
2014-05-26 14:09:26 -07:00
GL_CHECK ( glReadPixels ( 0
, 0
, width
, height
, m_readPixelsFmt
, GL_UNSIGNED_BYTE
, data
) ) ;
2014-04-06 21:30:32 -07:00
2014-05-26 14:09:26 -07:00
if ( GL_RGBA = = m_readPixelsFmt )
2014-04-06 21:30:32 -07:00
{
2014-05-26 14:09:26 -07:00
imageSwizzleBgra8 ( width , height , width * 4 , data , data ) ;
}
2014-04-06 21:30:32 -07:00
2014-05-26 14:09:26 -07:00
g_callback - > screenShot ( _filePath
, width
, height
, width * 4
, data
, length
, true
) ;
BX_FREE ( g_allocator , data ) ;
}
2014-04-06 21:30:32 -07:00
2016-02-11 08:58:51 -08:00
void readBack ( FrameBufferHandle _handle ) BX_OVERRIDE
2015-10-07 00:49:17 -07:00
{
2016-02-11 08:58:51 -08:00
const FrameBufferGL & framebuffer = m_frameBuffers [ _handle . idx ] ;
const uint32_t width = framebuffer . m_width ;
const uint32_t height = framebuffer . m_height ;
const uint32_t length = width * height * 4 ;
uint8_t * const data = ( uint8_t * ) BX_ALLOC ( g_allocator , length ) ;
setFrameBuffer ( _handle , height ) ;
GL_CHECK ( glViewport ( 0 , 0 , width , height ) ) ;
2016-03-08 23:56:54 -08:00
# if !BGFX_CONFIG_RENDERER_OPENGLES
// OpenGL ES doesn't support glReadBuffer but it's necessary elsewhere
2016-02-11 08:58:51 -08:00
GL_CHECK ( glReadBuffer ( GL_COLOR_ATTACHMENT0 ) ) ;
# endif
GL_CHECK ( glReadPixels ( 0
, 0
, width
, height
, m_readPixelsFmt
, GL_UNSIGNED_BYTE
, data
) ) ;
if ( GL_RGBA = = m_readPixelsFmt )
{
imageSwizzleBgra8 ( width , height , width * 4 , data , data ) ;
}
g_callback - > readBack ( _handle , width , height , width * 4 , data , length , true ) ;
2016-03-09 08:13:11 -08:00
// TODO: this call to glBindFramebuffer shouldn't be here
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ) ;
2016-02-11 08:58:51 -08:00
BX_FREE ( g_allocator , data ) ;
2015-10-07 00:49:17 -07:00
}
2014-05-26 14:09:26 -07:00
void updateViewName ( uint8_t _id , const char * _name ) BX_OVERRIDE
{
2015-11-16 10:42:56 -04:00
bx : : strlcpy ( & s_viewName [ _id ] [ BGFX_CONFIG_MAX_VIEW_NAME_RESERVED ]
, _name
, BX_COUNTOF ( s_viewName [ 0 ] ) - BGFX_CONFIG_MAX_VIEW_NAME_RESERVED
) ;
2014-05-26 14:09:26 -07:00
}
2014-04-06 21:30:32 -07:00
2014-05-26 14:09:26 -07:00
void updateUniform ( uint16_t _loc , const void * _data , uint32_t _size ) BX_OVERRIDE
{
memcpy ( m_uniforms [ _loc ] , _data , _size ) ;
}
2014-04-06 21:30:32 -07:00
2014-05-26 14:09:26 -07:00
void setMarker ( const char * _marker , uint32_t _size ) BX_OVERRIDE
{
GL_CHECK ( glInsertEventMarker ( _size , _marker ) ) ;
}
void submit ( Frame * _render , ClearQuad & _clearQuad , TextVideoMemBlitter & _textVideoMemBlitter ) BX_OVERRIDE ;
void blitSetup ( TextVideoMemBlitter & _blitter ) BX_OVERRIDE
{
if ( 0 ! = m_vao )
2014-04-06 21:30:32 -07:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindVertexArray ( m_vao ) ) ;
2014-04-06 21:30:32 -07:00
}
2014-10-28 22:08:55 -07:00
uint32_t width = m_resolution . m_width ;
2014-05-26 14:09:26 -07:00
uint32_t height = m_resolution . m_height ;
2014-10-28 22:08:55 -07:00
if ( m_ovr . isEnabled ( ) )
{
m_ovr . getSize ( width , height ) ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_backBufferFbo ) ) ;
GL_CHECK ( glViewport ( 0 , 0 , width , height ) ) ;
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
GL_CHECK ( glDisable ( GL_SCISSOR_TEST ) ) ;
GL_CHECK ( glDisable ( GL_STENCIL_TEST ) ) ;
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 ) ) ;
2014-03-26 23:37:01 -07:00
2014-05-26 14:09:26 -07:00
ProgramGL & program = m_program [ _blitter . m_program . idx ] ;
GL_CHECK ( glUseProgram ( program . m_id ) ) ;
GL_CHECK ( glUniform1i ( program . m_sampler [ 0 ] , 0 ) ) ;
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
float proj [ 16 ] ;
2015-04-10 19:21:31 -07:00
bx : : mtxOrtho ( proj , 0.0f , ( float ) width , ( float ) height , 0.0f , 0.0f , 1000.0f ) ;
2014-05-26 14:09:26 -07:00
GL_CHECK ( glUniformMatrix4fv ( program . m_predefined [ 0 ] . m_loc
, 1
, GL_FALSE
, proj
) ) ;
GL_CHECK ( glActiveTexture ( GL_TEXTURE0 ) ) ;
GL_CHECK ( glBindTexture ( GL_TEXTURE_2D , m_textures [ _blitter . m_texture . idx ] . m_id ) ) ;
2015-11-06 21:30:08 -08:00
2015-11-07 20:34:38 -08:00
if ( ! BX_ENABLED ( BX_PLATFORM_OSX ) )
2015-11-06 21:30:08 -08:00
{
2015-11-07 20:34:38 -08:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
{
2016-02-08 08:58:16 -08:00
if ( m_samplerObjectSupport )
{
GL_CHECK ( glBindSampler ( 0 , 0 ) ) ;
}
2015-11-07 20:34:38 -08:00
}
2015-11-06 21:30:08 -08:00
}
2014-05-26 14:09:26 -07:00
}
void blitRender ( TextVideoMemBlitter & _blitter , uint32_t _numIndices ) BX_OVERRIDE
{
2015-01-26 19:09:51 -08:00
const uint32_t numVertices = _numIndices * 4 / 6 ;
if ( 0 < numVertices )
{
m_indexBuffers [ _blitter . m_ib - > handle . idx ] . update ( 0 , _numIndices * 2 , _blitter . m_ib - > data ) ;
m_vertexBuffers [ _blitter . m_vb - > handle . idx ] . update ( 0 , numVertices * _blitter . m_decl . m_stride , _blitter . m_vb - > data ) ;
2014-05-26 14:09:26 -07:00
2015-01-26 19:09:51 -08:00
VertexBufferGL & vb = m_vertexBuffers [ _blitter . m_vb - > handle . idx ] ;
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , vb . m_id ) ) ;
2014-05-26 14:09:26 -07:00
2015-01-26 19:09:51 -08:00
IndexBufferGL & ib = m_indexBuffers [ _blitter . m_ib - > handle . idx ] ;
GL_CHECK ( glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , ib . m_id ) ) ;
2014-05-26 14:09:26 -07:00
2015-01-26 19:09:51 -08:00
ProgramGL & program = m_program [ _blitter . m_program . idx ] ;
program . bindAttributes ( _blitter . m_decl , 0 ) ;
2014-05-26 14:09:26 -07:00
2015-01-26 19:09:51 -08:00
GL_CHECK ( glDrawElements ( GL_TRIANGLES
, _numIndices
, GL_UNSIGNED_SHORT
, ( void * ) 0
) ) ;
}
2014-05-26 14:09:26 -07:00
}
void updateResolution ( const Resolution & _resolution )
{
2015-01-21 20:39:42 -08:00
bool recenter = ! ! ( _resolution . m_flags & BGFX_RESET_HMD_RECENTER ) ;
m_maxAnisotropy = ! ! ( _resolution . m_flags & BGFX_RESET_MAXANISOTROPY )
? m_maxAnisotropyDefault
: 0.0f
;
2015-12-13 12:17:08 -08:00
if ( s_extension [ Extension : : ARB_depth_clamp ] . m_supported )
{
if ( ! ! ( _resolution . m_flags & BGFX_RESET_DEPTH_CLAMP ) )
{
GL_CHECK ( glEnable ( GL_DEPTH_CLAMP ) ) ;
}
else
{
GL_CHECK ( glDisable ( GL_DEPTH_CLAMP ) ) ;
}
}
2016-03-08 15:44:42 -08:00
uint32_t flags = _resolution . m_flags & ~ ( 0
| BGFX_RESET_HMD_RECENTER
| BGFX_RESET_MAXANISOTROPY
| BGFX_RESET_DEPTH_CLAMP
| BGFX_RESET_SUSPEND
) ;
2014-11-02 00:06:18 -07:00
2014-10-28 22:08:55 -07:00
if ( m_resolution . m_width ! = _resolution . m_width
2014-06-22 18:51:14 -07:00
| | m_resolution . m_height ! = _resolution . m_height
2014-11-02 00:06:18 -07:00
| | m_resolution . m_flags ! = flags )
2014-03-04 22:20:37 -08:00
{
2015-11-01 17:28:23 -08:00
flags & = ~ BGFX_RESET_INTERNAL_FORCE ;
2015-10-21 16:55:50 -07:00
2014-05-26 14:09:26 -07:00
m_resolution = _resolution ;
2014-11-02 00:06:18 -07:00
m_resolution . m_flags = flags ;
2014-05-26 14:09:26 -07:00
2015-10-21 22:04:28 -07:00
m_textVideoMem . resize ( false , _resolution . m_width , _resolution . m_height ) ;
m_textVideoMem . clear ( ) ;
2015-06-05 09:54:14 -07:00
if ( ( flags & BGFX_RESET_HMD )
& & m_ovr . isInitialized ( ) )
2015-06-04 19:15:05 -07:00
{
flags & = ~ BGFX_RESET_MSAA_MASK ;
}
2015-04-06 21:31:26 -07:00
setRenderContextSize ( m_resolution . m_width
, m_resolution . m_height
2015-06-04 19:15:05 -07:00
, flags
2015-04-06 21:31:26 -07:00
) ;
2014-05-26 14:09:26 -07:00
updateCapture ( ) ;
2014-10-28 22:08:55 -07:00
2015-04-13 22:13:16 -07:00
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_frameBuffers ) ; + + ii )
{
2015-04-14 17:02:41 -07:00
m_frameBuffers [ ii ] . postReset ( ) ;
2015-04-13 22:13:16 -07:00
}
2014-10-28 22:08:55 -07:00
ovrPreReset ( ) ;
ovrPostReset ( ) ;
2014-03-04 22:20:37 -08:00
}
2014-11-02 00:06:18 -07:00
if ( recenter )
{
m_ovr . recenter ( ) ;
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2015-04-07 17:58:14 -07:00
void setShaderUniform4f ( uint8_t /*_flags*/ , uint32_t _regIndex , const void * _val , uint32_t _numRegs )
2014-12-27 19:00:41 -08:00
{
GL_CHECK ( glUniform4fv ( _regIndex
, _numRegs
, ( const GLfloat * ) _val
) ) ;
}
2015-04-07 17:58:14 -07:00
void setShaderUniform4x4f ( uint8_t /*_flags*/ , uint32_t _regIndex , const void * _val , uint32_t _numRegs )
2014-12-27 19:00:41 -08:00
{
GL_CHECK ( glUniformMatrix4fv ( _regIndex
, _numRegs
, GL_FALSE
, ( const GLfloat * ) _val
) ) ;
}
2015-04-07 17:58:14 -07:00
uint32_t setFrameBuffer ( FrameBufferHandle _fbh , uint32_t _height , uint16_t _discard = BGFX_CLEAR_NONE , bool _msaa = true )
2014-05-26 14:09:26 -07:00
{
if ( isValid ( m_fbh )
2014-06-22 18:51:14 -07:00
& & m_fbh . idx ! = _fbh . idx
2015-01-11 18:00:08 -08:00
& & ( BGFX_CLEAR_NONE ! = m_fbDiscard | | m_rtMsaa ) )
2014-05-26 14:09:26 -07:00
{
FrameBufferGL & frameBuffer = m_frameBuffers [ m_fbh . idx ] ;
2015-01-11 18:00:08 -08:00
if ( m_rtMsaa )
{
frameBuffer . resolve ( ) ;
}
if ( BGFX_CLEAR_NONE ! = m_fbDiscard )
{
frameBuffer . discard ( m_fbDiscard ) ;
}
m_fbDiscard = BGFX_CLEAR_NONE ;
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-09-07 17:17:38 -07:00
m_glctx . makeCurrent ( NULL ) ;
2014-05-26 14:09:26 -07:00
if ( ! isValid ( _fbh ) )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_msaaBackBufferFbo ) ) ;
2015-11-30 14:50:28 -08:00
if ( m_srgbWriteControlSupport )
2015-11-30 21:52:57 +01:00
{
2015-11-30 14:50:28 -08:00
if ( 0 ! = ( m_resolution . m_flags & BGFX_RESET_SRGB_BACKBUFFER ) )
{
GL_CHECK ( glEnable ( GL_FRAMEBUFFER_SRGB ) ) ;
}
else
{
GL_CHECK ( glDisable ( GL_FRAMEBUFFER_SRGB ) ) ;
}
2015-11-30 21:52:57 +01:00
}
2014-05-26 14:09:26 -07:00
}
else
{
FrameBufferGL & frameBuffer = m_frameBuffers [ _fbh . idx ] ;
2014-09-24 19:22:15 -07:00
_height = frameBuffer . m_height ;
2016-03-15 17:30:57 +01:00
if ( UINT16_MAX ! = frameBuffer . m_denseIdx )
{
m_glctx . makeCurrent ( frameBuffer . m_swapChain ) ;
}
else
{
m_glctx . makeCurrent ( NULL ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , frameBuffer . m_fbo [ 0 ] ) ) ;
}
2014-03-04 22:20:37 -08:00
}
2015-01-11 18:00:08 -08:00
m_fbh = _fbh ;
m_fbDiscard = _discard ;
m_rtMsaa = _msaa ;
2014-05-26 14:09:26 -07:00
return _height ;
}
uint32_t getNumRt ( ) const
{
if ( isValid ( m_fbh ) )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
const FrameBufferGL & frameBuffer = m_frameBuffers [ m_fbh . idx ] ;
return frameBuffer . m_num ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
return 1 ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void createMsaaFbo ( uint32_t _width , uint32_t _height , uint32_t _msaa )
{
if ( 0 = = m_msaaBackBufferFbo // iOS
2014-06-22 18:51:14 -07:00
& & 1 < _msaa )
2014-05-26 14:09:26 -07:00
{
GL_CHECK ( glGenFramebuffers ( 1 , & m_msaaBackBufferFbo ) ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_msaaBackBufferFbo ) ) ;
GL_CHECK ( glGenRenderbuffers ( BX_COUNTOF ( m_msaaBackBufferRbos ) , m_msaaBackBufferRbos ) ) ;
GL_CHECK ( glBindRenderbuffer ( GL_RENDERBUFFER , m_msaaBackBufferRbos [ 0 ] ) ) ;
GL_CHECK ( glRenderbufferStorageMultisample ( GL_RENDERBUFFER , _msaa , GL_RGBA8 , _width , _height ) ) ;
GL_CHECK ( glBindRenderbuffer ( GL_RENDERBUFFER , m_msaaBackBufferRbos [ 1 ] ) ) ;
GL_CHECK ( glRenderbufferStorageMultisample ( GL_RENDERBUFFER , _msaa , GL_DEPTH24_STENCIL8 , _width , _height ) ) ;
GL_CHECK ( glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER , m_msaaBackBufferRbos [ 0 ] ) ) ;
2014-03-04 22:20:37 -08:00
2015-01-08 20:43:36 -08:00
GLenum attachment = BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) | | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
2014-06-22 18:57:37 -07:00
? GL_DEPTH_STENCIL_ATTACHMENT
2015-01-08 20:43:36 -08:00
: GL_DEPTH_ATTACHMENT
2014-05-26 14:09:26 -07:00
;
GL_CHECK ( glFramebufferRenderbuffer ( GL_FRAMEBUFFER , attachment , GL_RENDERBUFFER , m_msaaBackBufferRbos [ 1 ] ) ) ;
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
BX_CHECK ( GL_FRAMEBUFFER_COMPLETE = = glCheckFramebufferStatus ( GL_FRAMEBUFFER )
, " glCheckFramebufferStatus failed 0x%08x "
, glCheckFramebufferStatus ( GL_FRAMEBUFFER )
) ;
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_msaaBackBufferFbo ) ) ;
}
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void destroyMsaaFbo ( )
{
if ( m_backBufferFbo ! = m_msaaBackBufferFbo // iOS
2014-06-22 18:51:14 -07:00
& & 0 ! = m_msaaBackBufferFbo )
2014-05-26 14:09:26 -07:00
{
GL_CHECK ( glDeleteFramebuffers ( 1 , & m_msaaBackBufferFbo ) ) ;
m_msaaBackBufferFbo = 0 ;
2014-10-28 21:41:34 -07:00
if ( 0 ! = m_msaaBackBufferRbos [ 0 ] )
{
GL_CHECK ( glDeleteRenderbuffers ( BX_COUNTOF ( m_msaaBackBufferRbos ) , m_msaaBackBufferRbos ) ) ;
m_msaaBackBufferRbos [ 0 ] = 0 ;
m_msaaBackBufferRbos [ 1 ] = 0 ;
}
2014-05-26 14:09:26 -07:00
}
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void blitMsaaFbo ( )
{
if ( m_backBufferFbo ! = m_msaaBackBufferFbo // iOS
2014-06-22 18:51:14 -07:00
& & 0 ! = m_msaaBackBufferFbo )
2013-06-09 15:28:25 -07:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glDisable ( GL_SCISSOR_TEST ) ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_backBufferFbo ) ) ;
GL_CHECK ( glBindFramebuffer ( GL_READ_FRAMEBUFFER , m_msaaBackBufferFbo ) ) ;
GL_CHECK ( glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , 0 ) ) ;
2014-10-28 22:08:55 -07:00
uint32_t width = m_resolution . m_width ;
2014-05-26 14:09:26 -07:00
uint32_t height = m_resolution . m_height ;
2015-01-08 20:43:36 -08:00
GLenum filter = BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) | | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES < 30 )
? GL_NEAREST
2014-05-26 14:09:26 -07:00
: GL_LINEAR
;
GL_CHECK ( glBlitFramebuffer ( 0
, 0
, width
, height
, 0
, 0
, width
, height
, GL_COLOR_BUFFER_BIT
, filter
) ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_backBufferFbo ) ) ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
}
2015-04-06 21:31:26 -07:00
void setRenderContextSize ( uint32_t _width , uint32_t _height , uint32_t _flags = 0 )
2014-05-26 14:09:26 -07:00
{
2014-09-24 19:22:15 -07:00
if ( _width ! = 0
2014-06-22 18:51:14 -07:00
| | _height ! = 0 )
2014-05-26 14:09:26 -07:00
{
if ( ! m_glctx . isValid ( ) )
{
m_glctx . create ( _width , _height ) ;
# if BX_PLATFORM_IOS
// iOS: need to figure out how to deal with FBO created by context.
2014-09-07 17:52:02 -07:00
m_backBufferFbo = m_msaaBackBufferFbo = m_glctx . getFbo ( ) ;
2014-05-26 14:09:26 -07:00
# endif // BX_PLATFORM_IOS
}
else
{
destroyMsaaFbo ( ) ;
2015-04-06 21:31:26 -07:00
m_glctx . resize ( _width , _height , _flags ) ;
2014-03-04 22:20:37 -08:00
2015-04-06 21:31:26 -07:00
uint32_t msaa = ( _flags & BGFX_RESET_MSAA_MASK ) > > BGFX_RESET_MSAA_SHIFT ;
msaa = bx : : uint32_min ( m_maxMsaa , msaa = = 0 ? 0 : 1 < < msaa ) ;
createMsaaFbo ( _width , _height , msaa ) ;
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
m_flip = true ;
}
void invalidateCache ( )
{
if ( m_vaoSupport )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
m_vaoStateCache . invalidate ( ) ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
if ( ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) | | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
2014-06-22 18:51:14 -07:00
& & m_samplerObjectSupport )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
m_samplerStateCache . invalidate ( ) ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
}
2015-09-16 17:21:28 -07:00
void setSamplerState ( uint32_t _stage , uint32_t _numMips , uint32_t _flags , const float _rgba [ 4 ] )
2014-05-26 14:09:26 -07:00
{
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
2014-06-22 18:51:14 -07:00
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
2014-03-04 22:20:37 -08:00
{
2015-11-01 17:28:23 -08:00
if ( 0 = = ( BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags ) )
2014-03-04 22:20:37 -08:00
{
2015-09-16 17:21:28 -07:00
const uint32_t index = ( _flags & BGFX_TEXTURE_BORDER_COLOR_MASK ) > > BGFX_TEXTURE_BORDER_COLOR_SHIFT ;
2014-05-26 14:09:26 -07:00
_flags & = ~ BGFX_TEXTURE_RESERVED_MASK ;
_flags & = BGFX_TEXTURE_SAMPLER_BITS_MASK ;
_flags | = _numMips < < BGFX_TEXTURE_RESERVED_SHIFT ;
2015-09-16 17:21:28 -07:00
GLuint sampler ;
bool hasBorderColor = false ;
bx : : HashMurmur2A murmur ;
uint32_t hash ;
murmur . begin ( ) ;
murmur . add ( _flags ) ;
2015-09-17 19:55:01 -07:00
if ( ! needBorderColor ( _flags ) )
2015-09-16 17:21:28 -07:00
{
murmur . add ( - 1 ) ;
hash = murmur . end ( ) ;
sampler = m_samplerStateCache . find ( hash ) ;
}
else
{
murmur . add ( index ) ;
hash = murmur . end ( ) ;
if ( NULL ! = _rgba )
{
hasBorderColor = true ;
sampler = UINT32_MAX ;
}
else
{
sampler = m_samplerStateCache . find ( hash ) ;
}
}
2014-05-26 14:09:26 -07:00
if ( UINT32_MAX = = sampler )
2014-03-04 22:20:37 -08:00
{
2015-09-16 17:21:28 -07:00
sampler = m_samplerStateCache . add ( hash ) ;
2014-05-26 14:09:26 -07:00
2015-03-28 21:25:40 -07:00
GL_CHECK ( glSamplerParameteri ( sampler
, GL_TEXTURE_WRAP_S
, s_textureAddress [ ( _flags & BGFX_TEXTURE_U_MASK ) > > BGFX_TEXTURE_U_SHIFT ]
) ) ;
GL_CHECK ( glSamplerParameteri ( sampler
, GL_TEXTURE_WRAP_T
, s_textureAddress [ ( _flags & BGFX_TEXTURE_V_MASK ) > > BGFX_TEXTURE_V_SHIFT ]
) ) ;
GL_CHECK ( glSamplerParameteri ( sampler
, GL_TEXTURE_WRAP_R
, s_textureAddress [ ( _flags & BGFX_TEXTURE_W_MASK ) > > BGFX_TEXTURE_W_SHIFT ]
) ) ;
GLenum minFilter ;
GLenum magFilter ;
getFilters ( _flags , 1 < _numMips , magFilter , minFilter ) ;
GL_CHECK ( glSamplerParameteri ( sampler , GL_TEXTURE_MAG_FILTER , magFilter ) ) ;
2014-05-26 14:09:26 -07:00
GL_CHECK ( glSamplerParameteri ( sampler , GL_TEXTURE_MIN_FILTER , minFilter ) ) ;
2015-03-28 21:25:40 -07:00
2015-09-12 09:25:37 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
| | m_borderColorSupport )
{
2015-09-16 17:21:28 -07:00
if ( hasBorderColor )
{
GL_CHECK ( glSamplerParameterfv ( sampler , GL_TEXTURE_BORDER_COLOR , _rgba ) ) ;
}
2015-09-12 09:25:37 -07:00
}
2015-09-11 20:05:13 -07:00
2014-05-26 14:09:26 -07:00
if ( 0 ! = ( _flags & ( BGFX_TEXTURE_MIN_ANISOTROPIC | BGFX_TEXTURE_MAG_ANISOTROPIC ) )
2014-06-22 18:51:14 -07:00
& & 0.0f < m_maxAnisotropy )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glSamplerParameterf ( sampler , GL_TEXTURE_MAX_ANISOTROPY_EXT , m_maxAnisotropy ) ) ;
}
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
2014-06-22 18:51:14 -07:00
| | m_shadowSamplersSupport )
2014-05-26 14:09:26 -07:00
{
const uint32_t cmpFunc = ( _flags & BGFX_TEXTURE_COMPARE_MASK ) > > BGFX_TEXTURE_COMPARE_SHIFT ;
if ( 0 = = cmpFunc )
{
GL_CHECK ( glSamplerParameteri ( sampler , GL_TEXTURE_COMPARE_MODE , GL_NONE ) ) ;
}
else
{
GL_CHECK ( glSamplerParameteri ( sampler , GL_TEXTURE_COMPARE_MODE , GL_COMPARE_REF_TO_TEXTURE ) ) ;
GL_CHECK ( glSamplerParameteri ( sampler , GL_TEXTURE_COMPARE_FUNC , s_cmpFunc [ cmpFunc ] ) ) ;
}
2014-03-04 22:20:37 -08:00
}
}
2014-03-05 20:51:44 -08:00
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindSampler ( _stage , sampler ) ) ;
}
else
2014-03-05 20:51:44 -08:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindSampler ( _stage , 0 ) ) ;
2014-03-05 20:51:44 -08:00
}
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2015-11-03 16:00:14 -08:00
bool isVisible ( Frame * _render , OcclusionQueryHandle _handle , bool _visible )
2015-11-01 19:12:42 -08:00
{
2015-11-03 16:00:14 -08:00
m_occlusionQuery . resolve ( _render ) ;
2015-11-03 19:06:14 -08:00
return _visible = = ( 0 ! = _render - > m_occlusion [ _handle . idx ] ) ;
2015-11-01 19:12:42 -08:00
}
2014-10-28 22:08:55 -07:00
void ovrPostReset ( )
{
# if BGFX_CONFIG_USE_OVR
if ( m_resolution . m_flags & ( BGFX_RESET_HMD | BGFX_RESET_HMD_DEBUG ) )
{
ovrGLConfig config ;
config . OGL . Header . API = ovrRenderAPI_OpenGL ;
2014-12-21 18:55:33 -08:00
# if OVR_VERSION > OVR_VERSION_043
2014-12-05 19:17:59 -08:00
config . OGL . Header . BackBufferSize . w = m_resolution . m_width ;
config . OGL . Header . BackBufferSize . h = m_resolution . m_height ;
2014-12-21 18:55:33 -08:00
# else
config . OGL . Header . RTSize . w = m_resolution . m_width ;
config . OGL . Header . RTSize . h = m_resolution . m_height ;
# endif // OVR_VERSION > OVR_VERSION_043
2014-10-28 22:08:55 -07:00
config . OGL . Header . Multisample = 0 ;
2015-04-25 16:56:29 -07:00
config . OGL . Window = ( HWND ) g_platformData . nwh ;
config . OGL . DC = GetDC ( config . OGL . Window ) ;
2015-04-20 16:22:40 -07:00
if ( m_ovr . postReset ( g_platformData . nwh , & config . Config , ! ! ( m_resolution . m_flags & BGFX_RESET_HMD_DEBUG ) ) )
2014-10-28 22:08:55 -07:00
{
uint32_t size = sizeof ( uint32_t ) + sizeof ( TextureCreate ) ;
const Memory * mem = alloc ( size ) ;
bx : : StaticMemoryBlockWriter writer ( mem - > data , mem - > size ) ;
uint32_t magic = BGFX_CHUNK_MAGIC_TEX ;
bx : : write ( & writer , magic ) ;
TextureCreate tc ;
2015-07-16 20:28:43 -07:00
tc . m_flags = BGFX_TEXTURE_RT | ( ( ( m_resolution . m_flags & BGFX_RESET_MSAA_MASK ) > > BGFX_RESET_MSAA_SHIFT ) < < BGFX_TEXTURE_RT_MSAA_SHIFT ) ; ;
2014-10-28 22:08:55 -07:00
tc . m_width = m_ovr . m_rtSize . w ;
tc . m_height = m_ovr . m_rtSize . h ;
tc . m_sides = 0 ;
tc . m_depth = 0 ;
tc . m_numMips = 1 ;
tc . m_format = uint8_t ( bgfx : : TextureFormat : : BGRA8 ) ;
tc . m_cubeMap = false ;
tc . m_mem = NULL ;
bx : : write ( & writer , tc ) ;
m_ovrRT . create ( mem , tc . m_flags , 0 ) ;
release ( mem ) ;
m_ovrFbo = m_msaaBackBufferFbo ;
GL_CHECK ( glGenFramebuffers ( 1 , & m_msaaBackBufferFbo ) ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_msaaBackBufferFbo ) ) ;
GL_CHECK ( glFramebufferTexture2D ( GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, m_ovrRT . m_id
, 0
) ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_ovrFbo ) ) ;
ovrGLTexture texture ;
texture . OGL . Header . API = ovrRenderAPI_OpenGL ;
texture . OGL . Header . TextureSize = m_ovr . m_rtSize ;
texture . OGL . TexId = m_ovrRT . m_id ;
m_ovr . postReset ( texture . Texture ) ;
}
}
# endif // BGFX_CONFIG_USE_OVR
}
void ovrPreReset ( )
{
# if BGFX_CONFIG_USE_OVR
2014-11-12 21:26:28 -08:00
m_ovr . preReset ( ) ;
2014-10-28 22:08:55 -07:00
if ( m_ovr . isEnabled ( ) )
{
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ) ;
GL_CHECK ( glDeleteFramebuffers ( 1 , & m_msaaBackBufferFbo ) ) ;
m_msaaBackBufferFbo = m_ovrFbo ;
m_ovrFbo = 0 ;
m_ovrRT . destroy ( ) ;
}
# endif // BGFX_CONFIG_USE_OVR
}
2014-05-26 14:09:26 -07:00
void updateCapture ( )
{
if ( m_resolution . m_flags & BGFX_RESET_CAPTURE )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
m_captureSize = m_resolution . m_width * m_resolution . m_height * 4 ;
m_capture = BX_REALLOC ( g_allocator , m_capture , m_captureSize ) ;
g_callback - > captureBegin ( m_resolution . m_width , m_resolution . m_height , m_resolution . m_width * 4 , TextureFormat : : BGRA8 , true ) ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
else
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
captureFinish ( ) ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void capture ( )
{
if ( NULL ! = m_capture )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glReadPixels ( 0
, 0
, m_resolution . m_width
, m_resolution . m_height
, m_readPixelsFmt
, GL_UNSIGNED_BYTE
, m_capture
) ) ;
2014-03-04 22:20:37 -08:00
2016-01-10 22:55:33 -05:00
if ( GL_RGBA = = m_readPixelsFmt )
{
imageSwizzleBgra8 ( m_resolution . m_width , m_resolution . m_height , m_resolution . m_width * 4 , m_capture , m_capture ) ;
}
2014-05-26 14:09:26 -07:00
g_callback - > captureFrame ( m_capture , m_captureSize ) ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
void captureFinish ( )
{
if ( NULL ! = m_capture )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
g_callback - > captureEnd ( ) ;
BX_FREE ( g_allocator , m_capture ) ;
m_capture = NULL ;
m_captureSize = 0 ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
bool programFetchFromCache ( GLuint programId , uint64_t _id )
{
_id ^ = m_hash ;
bool cached = false ;
if ( m_programBinarySupport )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
uint32_t length = g_callback - > cacheReadSize ( _id ) ;
cached = length > 0 ;
if ( cached )
{
void * data = BX_ALLOC ( g_allocator , length ) ;
if ( g_callback - > cacheRead ( _id , data , length ) )
{
bx : : MemoryReader reader ( data , length ) ;
GLenum format ;
bx : : read ( & reader , format ) ;
GL_CHECK ( glProgramBinary ( programId , format , reader . getDataPtr ( ) , ( GLsizei ) reader . remaining ( ) ) ) ;
}
BX_FREE ( g_allocator , data ) ;
}
# if BGFX_CONFIG_RENDERER_OPENGL
GL_CHECK ( glProgramParameteri ( programId , GL_PROGRAM_BINARY_RETRIEVABLE_HINT , GL_TRUE ) ) ;
# endif // BGFX_CONFIG_RENDERER_OPENGL
2013-06-09 15:28:25 -07:00
}
2014-05-26 14:09:26 -07:00
return cached ;
}
void programCache ( GLuint programId , uint64_t _id )
{
_id ^ = m_hash ;
if ( m_programBinarySupport )
2014-03-09 21:20:34 -07:00
{
2014-05-26 14:09:26 -07:00
GLint programLength ;
GLenum format ;
GL_CHECK ( glGetProgramiv ( programId , GL_PROGRAM_BINARY_LENGTH , & programLength ) ) ;
if ( 0 < programLength )
{
uint32_t length = programLength + 4 ;
uint8_t * data = ( uint8_t * ) BX_ALLOC ( g_allocator , length ) ;
GL_CHECK ( glGetProgramBinary ( programId , programLength , NULL , & format , & data [ 4 ] ) ) ;
* ( uint32_t * ) data = format ;
g_callback - > cacheWrite ( _id , data , length ) ;
BX_FREE ( g_allocator , data ) ;
}
2014-03-09 21:20:34 -07:00
}
2014-05-26 14:09:26 -07:00
}
2014-03-09 21:20:34 -07:00
2015-09-14 15:53:33 -07:00
void commit ( UniformBuffer & _uniformBuffer )
2014-05-26 14:09:26 -07:00
{
2015-09-14 15:53:33 -07:00
_uniformBuffer . reset ( ) ;
2014-05-26 14:09:26 -07:00
2014-06-08 20:57:39 -07:00
for ( ; ; )
2014-02-20 23:03:31 -08:00
{
2015-09-14 15:53:33 -07:00
uint32_t opcode = _uniformBuffer . read ( ) ;
2014-05-26 14:09:26 -07:00
if ( UniformType : : End = = opcode )
{
break ;
}
UniformType : : Enum type ;
uint16_t ignore ;
uint16_t num ;
uint16_t copy ;
2015-09-14 15:53:33 -07:00
UniformBuffer : : decodeOpcode ( opcode , type , ignore , num , copy ) ;
2014-05-26 14:09:26 -07:00
const char * data ;
if ( copy )
{
2015-09-14 15:53:33 -07:00
data = _uniformBuffer . read ( g_uniformTypeSize [ type ] * num ) ;
2014-05-26 14:09:26 -07:00
}
else
{
UniformHandle handle ;
2015-09-14 15:53:33 -07:00
memcpy ( & handle , _uniformBuffer . read ( sizeof ( UniformHandle ) ) , sizeof ( UniformHandle ) ) ;
2014-05-26 14:09:26 -07:00
data = ( const char * ) m_uniforms [ handle . idx ] ;
}
2015-09-14 15:53:33 -07:00
uint32_t loc = _uniformBuffer . read ( ) ;
2014-05-26 14:09:26 -07:00
# define CASE_IMPLEMENT_UNIFORM(_uniform, _glsuffix, _dxsuffix, _type) \
case UniformType : : _uniform : \
{ \
_type * value = ( _type * ) data ; \
GL_CHECK ( glUniform # # _glsuffix ( loc , num , value ) ) ; \
} \
break ;
# define CASE_IMPLEMENT_UNIFORM_T(_uniform, _glsuffix, _dxsuffix, _type) \
case UniformType : : _uniform : \
{ \
_type * value = ( _type * ) data ; \
GL_CHECK ( glUniform # # _glsuffix ( loc , num , GL_FALSE , value ) ) ; \
} \
break ;
switch ( type )
{
2015-05-28 15:27:00 -07:00
// case ConstantType::Int1:
2014-05-26 14:09:26 -07:00
// {
// int* value = (int*)data;
2015-05-28 15:27:00 -07:00
// BX_TRACE("Int1 sampler %d, loc %d (num %d, copy %d)", *value, loc, num, copy);
2014-05-26 14:09:26 -07:00
// GL_CHECK(glUniform1iv(loc, num, value) );
// }
// break;
2015-08-20 12:30:59 -07:00
CASE_IMPLEMENT_UNIFORM ( Int1 , 1 iv , I , int ) ;
CASE_IMPLEMENT_UNIFORM ( Vec4 , 4f v , F , float ) ;
CASE_IMPLEMENT_UNIFORM_T ( Mat3 , Matrix3fv , F , float ) ;
CASE_IMPLEMENT_UNIFORM_T ( Mat4 , Matrix4fv , F , float ) ;
2014-05-26 14:09:26 -07:00
case UniformType : : End :
break ;
default :
2015-09-14 15:53:33 -07:00
BX_TRACE ( " %4d: INVALID 0x%08x, t %d, l %d, n %d, c %d " , _uniformBuffer . getPos ( ) , opcode , type , loc , num , copy ) ;
2014-05-26 14:09:26 -07:00
break ;
}
# undef CASE_IMPLEMENT_UNIFORM
# undef CASE_IMPLEMENT_UNIFORM_T
2014-06-08 20:57:39 -07:00
}
2012-07-08 19:10:07 -07:00
}
2014-09-01 11:24:51 -07:00
void clearQuad ( ClearQuad & _clearQuad , const Rect & _rect , const Clear & _clear , uint32_t _height , const float _palette [ ] [ 4 ] )
2012-07-08 19:10:07 -07:00
{
2014-09-01 11:24:51 -07:00
uint32_t numMrt = 1 ;
FrameBufferHandle fbh = m_fbh ;
if ( isValid ( fbh ) )
{
const FrameBufferGL & fb = m_frameBuffers [ fbh . idx ] ;
numMrt = bx : : uint32_max ( 1 , fb . m_num ) ;
}
if ( 1 = = numMrt )
{
GLuint flags = 0 ;
2015-01-10 21:39:45 -08:00
if ( BGFX_CLEAR_COLOR & _clear . m_flags )
2014-09-01 11:24:51 -07:00
{
2015-01-11 18:00:08 -08:00
if ( BGFX_CLEAR_COLOR_USE_PALETTE & _clear . m_flags )
2014-09-01 11:24:51 -07:00
{
2015-09-16 17:21:28 -07:00
uint8_t index = ( uint8_t ) bx : : uint32_min ( BGFX_CONFIG_MAX_COLOR_PALETTE - 1 , _clear . m_index [ 0 ] ) ;
2014-09-01 11:24:51 -07:00
const float * rgba = _palette [ index ] ;
const float rr = rgba [ 0 ] ;
const float gg = rgba [ 1 ] ;
const float bb = rgba [ 2 ] ;
const float aa = rgba [ 3 ] ;
GL_CHECK ( glClearColor ( rr , gg , bb , aa ) ) ;
}
else
{
float rr = _clear . m_index [ 0 ] * 1.0f / 255.0f ;
float gg = _clear . m_index [ 1 ] * 1.0f / 255.0f ;
float bb = _clear . m_index [ 2 ] * 1.0f / 255.0f ;
float aa = _clear . m_index [ 3 ] * 1.0f / 255.0f ;
GL_CHECK ( glClearColor ( rr , gg , bb , aa ) ) ;
}
flags | = GL_COLOR_BUFFER_BIT ;
GL_CHECK ( glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ) ;
}
2015-01-10 21:39:45 -08:00
if ( BGFX_CLEAR_DEPTH & _clear . m_flags )
2014-09-01 11:24:51 -07:00
{
flags | = GL_DEPTH_BUFFER_BIT ;
GL_CHECK ( glClearDepth ( _clear . m_depth ) ) ;
GL_CHECK ( glDepthMask ( GL_TRUE ) ) ;
}
2015-01-10 21:39:45 -08:00
if ( BGFX_CLEAR_STENCIL & _clear . m_flags )
2014-09-01 11:24:51 -07:00
{
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 ) ) ;
}
}
else
2014-05-26 14:09:26 -07:00
{
const GLuint defaultVao = m_vao ;
if ( 0 ! = defaultVao )
{
GL_CHECK ( glBindVertexArray ( defaultVao ) ) ;
}
GL_CHECK ( glDisable ( GL_SCISSOR_TEST ) ) ;
GL_CHECK ( glDisable ( GL_CULL_FACE ) ) ;
GL_CHECK ( glDisable ( GL_BLEND ) ) ;
2015-01-10 21:39:45 -08:00
GLboolean colorMask = ! ! ( BGFX_CLEAR_COLOR & _clear . m_flags ) ;
2014-05-26 14:09:26 -07:00
GL_CHECK ( glColorMask ( colorMask , colorMask , colorMask , colorMask ) ) ;
2015-01-10 21:39:45 -08:00
if ( BGFX_CLEAR_DEPTH & _clear . m_flags )
2014-05-26 14:09:26 -07:00
{
GL_CHECK ( glEnable ( GL_DEPTH_TEST ) ) ;
GL_CHECK ( glDepthFunc ( GL_ALWAYS ) ) ;
GL_CHECK ( glDepthMask ( GL_TRUE ) ) ;
}
else
{
GL_CHECK ( glDisable ( GL_DEPTH_TEST ) ) ;
}
2015-01-10 21:39:45 -08:00
if ( BGFX_CLEAR_STENCIL & _clear . m_flags )
2014-05-26 14:09:26 -07:00
{
GL_CHECK ( glEnable ( GL_STENCIL_TEST ) ) ;
GL_CHECK ( glStencilFuncSeparate ( GL_FRONT_AND_BACK , GL_ALWAYS , _clear . m_stencil , 0xff ) ) ;
GL_CHECK ( glStencilOpSeparate ( GL_FRONT_AND_BACK , GL_REPLACE , GL_REPLACE , GL_REPLACE ) ) ;
}
else
{
GL_CHECK ( glDisable ( GL_STENCIL_TEST ) ) ;
}
VertexBufferGL & vb = m_vertexBuffers [ _clearQuad . m_vb - > handle . idx ] ;
VertexDecl & vertexDecl = m_vertexDecls [ _clearQuad . m_vb - > decl . idx ] ;
{
struct Vertex
{
float m_x ;
float m_y ;
float m_z ;
2014-09-01 11:24:51 -07:00
} ;
2015-01-08 20:43:36 -08:00
2014-09-01 11:24:51 -07:00
Vertex * vertex = ( Vertex * ) _clearQuad . m_vb - > data ;
2014-05-26 14:09:26 -07:00
BX_CHECK ( vertexDecl . m_stride = = sizeof ( Vertex ) , " Stride/Vertex mismatch (stride %d, sizeof(Vertex) %d) " , vertexDecl . m_stride , sizeof ( Vertex ) ) ;
2015-08-21 10:58:22 -07:00
const float depth = _clear . m_depth * 2.0f - 1.0f ;
2014-05-26 14:09:26 -07:00
vertex - > m_x = - 1.0f ;
vertex - > m_y = - 1.0f ;
vertex - > m_z = depth ;
vertex + + ;
vertex - > m_x = 1.0f ;
vertex - > m_y = - 1.0f ;
vertex - > m_z = depth ;
vertex + + ;
2014-09-01 11:24:51 -07:00
vertex - > m_x = - 1.0f ;
2014-05-26 14:09:26 -07:00
vertex - > m_y = 1.0f ;
vertex - > m_z = depth ;
vertex + + ;
2014-09-01 11:24:51 -07:00
vertex - > m_x = 1.0f ;
2014-05-26 14:09:26 -07:00
vertex - > m_y = 1.0f ;
vertex - > m_z = depth ;
}
2014-09-01 11:24:51 -07:00
vb . update ( 0 , 4 * _clearQuad . m_decl . m_stride , _clearQuad . m_vb - > data ) ;
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , vb . m_id ) ) ;
2014-09-01 11:24:51 -07:00
ProgramGL & program = m_program [ _clearQuad . m_program [ numMrt - 1 ] . idx ] ;
2014-05-26 14:09:26 -07:00
GL_CHECK ( glUseProgram ( program . m_id ) ) ;
program . bindAttributes ( vertexDecl , 0 ) ;
2013-01-12 19:13:51 -08:00
2016-01-05 18:32:24 -08:00
float mrtClear [ BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ] [ 4 ] ;
2015-01-11 18:00:08 -08:00
if ( BGFX_CLEAR_COLOR_USE_PALETTE & _clear . m_flags )
2014-05-26 14:09:26 -07:00
{
2014-09-01 11:24:51 -07:00
for ( uint32_t ii = 0 ; ii < numMrt ; + + ii )
{
2015-09-16 17:21:28 -07:00
uint8_t index = ( uint8_t ) bx : : uint32_min ( BGFX_CONFIG_MAX_COLOR_PALETTE - 1 , _clear . m_index [ ii ] ) ;
2014-09-01 11:24:51 -07:00
memcpy ( mrtClear [ ii ] , _palette [ index ] , 16 ) ;
}
2014-05-26 14:09:26 -07:00
}
2014-09-01 11:24:51 -07:00
else
2014-05-26 14:09:26 -07:00
{
2014-09-01 11:24:51 -07:00
float rgba [ 4 ] =
{
2016-01-05 18:32:24 -08:00
_clear . m_index [ 0 ] * 1.0f / 255.0f ,
_clear . m_index [ 1 ] * 1.0f / 255.0f ,
_clear . m_index [ 2 ] * 1.0f / 255.0f ,
_clear . m_index [ 3 ] * 1.0f / 255.0f ,
2014-09-01 11:24:51 -07:00
} ;
2016-01-05 18:32:24 -08:00
for ( uint32_t ii = 0 ; ii < numMrt ; + + ii )
{
memcpy ( mrtClear [ ii ] , rgba , 16 ) ;
}
2014-05-26 14:09:26 -07:00
}
2016-01-05 18:32:24 -08:00
GL_CHECK ( glUniform4fv ( 0 , numMrt , mrtClear [ 0 ] ) ) ;
2014-09-01 11:24:51 -07:00
GL_CHECK ( glDrawArrays ( GL_TRIANGLE_STRIP
, 0
, 4
) ) ;
2014-05-26 14:09:26 -07:00
}
2012-07-08 19:10:07 -07:00
}
2014-12-11 20:48:16 -08:00
void * m_renderdocdll ;
2014-09-07 17:17:38 -07:00
uint16_t m_numWindows ;
FrameBufferHandle m_windows [ BGFX_CONFIG_MAX_FRAME_BUFFERS ] ;
2014-05-26 14:09:26 -07:00
IndexBufferGL m_indexBuffers [ BGFX_CONFIG_MAX_INDEX_BUFFERS ] ;
VertexBufferGL m_vertexBuffers [ BGFX_CONFIG_MAX_VERTEX_BUFFERS ] ;
ShaderGL m_shaders [ BGFX_CONFIG_MAX_SHADERS ] ;
ProgramGL m_program [ BGFX_CONFIG_MAX_PROGRAMS ] ;
TextureGL m_textures [ BGFX_CONFIG_MAX_TEXTURES ] ;
2012-07-08 19:10:07 -07:00
VertexDecl m_vertexDecls [ BGFX_CONFIG_MAX_VERTEX_DECLS ] ;
2014-05-26 14:09:26 -07:00
FrameBufferGL m_frameBuffers [ BGFX_CONFIG_MAX_FRAME_BUFFERS ] ;
2012-07-08 19:10:07 -07:00
UniformRegistry m_uniformReg ;
void * m_uniforms [ BGFX_CONFIG_MAX_UNIFORMS ] ;
2015-11-01 19:12:42 -08:00
2015-08-16 15:37:46 -07:00
TimerQueryGL m_gpuTimer ;
2015-11-01 19:12:42 -08:00
OcclusionQueryGL m_occlusionQuery ;
2012-07-08 19:10:07 -07:00
2013-07-24 21:59:59 -07:00
VaoStateCache m_vaoStateCache ;
SamplerStateCache m_samplerStateCache ;
2013-01-12 19:13:51 -08:00
2012-07-08 19:10:07 -07:00
TextVideoMem m_textVideoMem ;
2013-02-17 20:42:33 -08:00
bool m_rtMsaa ;
2012-07-08 19:10:07 -07:00
2014-02-05 23:07:11 -08:00
FrameBufferHandle m_fbh ;
2015-04-07 17:58:14 -07:00
uint16_t m_fbDiscard ;
2014-02-05 23:07:11 -08:00
2012-07-08 19:10:07 -07:00
Resolution m_resolution ;
2012-12-30 20:52:47 -08:00
void * m_capture ;
uint32_t m_captureSize ;
2012-12-09 19:20:32 -08:00
float m_maxAnisotropy ;
2015-01-21 20:39:42 -08:00
float m_maxAnisotropyDefault ;
2013-02-17 20:42:33 -08:00
int32_t m_maxMsaa ;
2013-03-03 22:30:50 -08:00
GLuint m_vao ;
2015-10-16 17:42:40 -07:00
bool m_blitSupported ;
2015-10-20 16:32:08 -07:00
bool m_readBackSupported ;
2013-01-12 19:13:51 -08:00
bool m_vaoSupport ;
2013-07-24 21:59:59 -07:00
bool m_samplerObjectSupport ;
2014-02-23 11:21:23 -08:00
bool m_shadowSamplersSupport ;
2015-11-30 14:50:28 -08:00
bool m_srgbWriteControlSupport ;
2015-09-12 09:25:37 -07:00
bool m_borderColorSupport ;
2012-11-08 20:29:58 -08:00
bool m_programBinarySupport ;
2013-01-06 12:39:18 -08:00
bool m_textureSwizzleSupport ;
2014-01-12 13:51:26 -08:00
bool m_depthTextureSupport ;
2015-03-30 00:06:34 -07:00
bool m_timerQuerySupport ;
2015-11-01 19:12:42 -08:00
bool m_occlusionQuerySupport ;
2016-03-16 20:04:06 -07:00
bool m_atocSupport ;
bool m_conservativeRasterSupport ;
2012-07-08 19:10:07 -07:00
bool m_flip ;
uint64_t m_hash ;
2013-09-02 19:50:18 -07:00
GLenum m_readPixelsFmt ;
2013-02-20 22:13:32 -08:00
GLuint m_backBufferFbo ;
2013-07-22 21:20:43 -07:00
GLuint m_msaaBackBufferFbo ;
GLuint m_msaaBackBufferRbos [ 2 ] ;
2013-01-13 18:39:25 -08:00
GlContext m_glctx ;
2013-04-20 23:13:44 -07:00
const char * m_vendor ;
const char * m_renderer ;
const char * m_version ;
const char * m_glslVersion ;
2014-10-28 22:08:55 -07:00
OVR m_ovr ;
TextureGL m_ovrRT ;
GLint m_ovrFbo ;
2012-07-08 19:10:07 -07:00
} ;
2014-05-26 14:09:26 -07:00
RendererContextGL * s_renderGL ;
2015-03-21 22:11:59 -07:00
RendererContextI * rendererCreate ( )
2014-05-26 14:09:26 -07:00
{
s_renderGL = BX_NEW ( g_allocator , RendererContextGL ) ;
2014-10-13 21:14:51 -07:00
s_renderGL - > init ( ) ;
2014-05-26 14:09:26 -07:00
return s_renderGL ;
}
2015-03-21 22:11:59 -07:00
void rendererDestroy ( )
2014-05-26 14:09:26 -07:00
{
2014-10-13 21:14:51 -07:00
s_renderGL - > shutdown ( ) ;
2014-05-26 14:09:26 -07:00
BX_DELETE ( g_allocator , s_renderGL ) ;
s_renderGL = NULL ;
}
2012-07-08 19:10:07 -07:00
const char * glslTypeName ( GLuint _type )
{
# define GLSL_TYPE(_ty) case _ty: return #_ty
switch ( _type )
{
2014-07-20 20:27:13 -07:00
GLSL_TYPE ( GL_INT ) ;
GLSL_TYPE ( GL_INT_VEC2 ) ;
GLSL_TYPE ( GL_INT_VEC3 ) ;
2015-01-08 20:43:36 -08:00
GLSL_TYPE ( GL_INT_VEC4 ) ;
2014-07-20 20:27:13 -07:00
GLSL_TYPE ( GL_UNSIGNED_INT ) ;
GLSL_TYPE ( GL_UNSIGNED_INT_VEC2 ) ;
GLSL_TYPE ( GL_UNSIGNED_INT_VEC3 ) ;
GLSL_TYPE ( GL_UNSIGNED_INT_VEC4 ) ;
2012-07-08 19:10:07 -07:00
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 ) ;
2015-03-16 21:44:33 -07:00
GLSL_TYPE ( GL_SAMPLER_2D ) ;
GLSL_TYPE ( GL_INT_SAMPLER_2D ) ;
GLSL_TYPE ( GL_UNSIGNED_INT_SAMPLER_2D ) ;
2012-11-25 18:24:50 -08:00
GLSL_TYPE ( GL_SAMPLER_3D ) ;
2015-03-16 21:44:33 -07:00
GLSL_TYPE ( GL_INT_SAMPLER_3D ) ;
GLSL_TYPE ( GL_UNSIGNED_INT_SAMPLER_3D ) ;
2012-07-08 19:10:07 -07:00
GLSL_TYPE ( GL_SAMPLER_CUBE ) ;
2015-03-16 21:44:33 -07:00
GLSL_TYPE ( GL_INT_SAMPLER_CUBE ) ;
GLSL_TYPE ( GL_UNSIGNED_INT_SAMPLER_CUBE ) ;
2014-02-23 11:21:23 -08:00
GLSL_TYPE ( GL_SAMPLER_2D_SHADOW ) ;
2015-03-16 21:44:33 -07:00
2014-07-20 20:27:13 -07:00
GLSL_TYPE ( GL_IMAGE_1D ) ;
2015-03-16 21:44:33 -07:00
GLSL_TYPE ( GL_INT_IMAGE_1D ) ;
2015-02-19 16:23:27 -08:00
GLSL_TYPE ( GL_UNSIGNED_INT_IMAGE_1D ) ;
2015-03-16 21:44:33 -07:00
GLSL_TYPE ( GL_IMAGE_2D ) ;
GLSL_TYPE ( GL_INT_IMAGE_2D ) ;
2015-02-19 16:23:27 -08:00
GLSL_TYPE ( GL_UNSIGNED_INT_IMAGE_2D ) ;
2015-03-16 21:44:33 -07:00
GLSL_TYPE ( GL_IMAGE_3D ) ;
GLSL_TYPE ( GL_INT_IMAGE_3D ) ;
2015-02-19 16:23:27 -08:00
GLSL_TYPE ( GL_UNSIGNED_INT_IMAGE_3D ) ;
2015-03-16 21:44:33 -07:00
GLSL_TYPE ( GL_IMAGE_CUBE ) ;
GLSL_TYPE ( GL_INT_IMAGE_CUBE ) ;
2015-02-19 16:23:27 -08:00
GLSL_TYPE ( GL_UNSIGNED_INT_IMAGE_CUBE ) ;
2012-07-08 19:10:07 -07:00
}
# undef GLSL_TYPE
2014-07-20 20:27:13 -07:00
BX_CHECK ( false , " Unknown GLSL type? %x " , _type ) ;
2012-07-08 19:10:07 -07:00
return " UNKNOWN GLSL TYPE! " ;
}
const char * glEnumName ( GLenum _enum )
{
# define GLENUM(_ty) case _ty: return #_ty
switch ( _enum )
{
GLENUM ( GL_TEXTURE ) ;
GLENUM ( GL_RENDERBUFFER ) ;
2014-04-01 22:31:02 -07:00
GLENUM ( GL_INVALID_ENUM ) ;
2015-03-24 21:24:13 -07:00
GLENUM ( GL_INVALID_FRAMEBUFFER_OPERATION ) ;
2014-04-01 22:31:02 -07:00
GLENUM ( GL_INVALID_VALUE ) ;
GLENUM ( GL_INVALID_OPERATION ) ;
GLENUM ( GL_OUT_OF_MEMORY ) ;
GLENUM ( GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ) ;
GLENUM ( GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT ) ;
// GLENUM(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
// GLENUM(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
GLENUM ( GL_FRAMEBUFFER_UNSUPPORTED ) ;
2012-07-08 19:10:07 -07:00
}
# undef GLENUM
2014-07-20 20:27:13 -07:00
BX_WARN ( false , " Unknown enum? %x " , _enum ) ;
2014-04-01 22:31:02 -07:00
return " <GLenum?> " ;
2012-07-08 19:10:07 -07:00
}
2012-10-27 21:34:41 -07:00
UniformType : : Enum convertGlType ( GLenum _type )
2012-07-08 19:10:07 -07:00
{
switch ( _type )
{
2014-04-26 23:48:41 -07:00
case GL_INT :
2014-07-20 20:27:13 -07:00
case GL_UNSIGNED_INT :
2015-05-28 15:27:00 -07:00
return UniformType : : Int1 ;
2014-04-26 23:48:41 -07:00
2012-07-08 19:10:07 -07:00
case GL_FLOAT :
case GL_FLOAT_VEC2 :
case GL_FLOAT_VEC3 :
case GL_FLOAT_VEC4 :
2015-05-28 15:27:00 -07:00
return UniformType : : Vec4 ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT_MAT2 :
break ;
case GL_FLOAT_MAT3 :
2015-05-28 15:27:00 -07:00
return UniformType : : Mat3 ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT_MAT4 :
2015-05-28 15:27:00 -07:00
return UniformType : : Mat4 ;
2012-07-08 19:10:07 -07:00
case GL_SAMPLER_2D :
2015-03-16 21:44:33 -07:00
case GL_INT_SAMPLER_2D :
case GL_UNSIGNED_INT_SAMPLER_2D :
2012-11-25 18:24:50 -08:00
case GL_SAMPLER_3D :
2015-03-16 21:44:33 -07:00
case GL_INT_SAMPLER_3D :
case GL_UNSIGNED_INT_SAMPLER_3D :
2012-07-08 19:10:07 -07:00
case GL_SAMPLER_CUBE :
2015-03-16 21:44:33 -07:00
case GL_INT_SAMPLER_CUBE :
case GL_UNSIGNED_INT_SAMPLER_CUBE :
case GL_SAMPLER_2D_SHADOW :
2014-07-20 20:27:13 -07:00
case GL_IMAGE_1D :
2015-03-16 21:44:33 -07:00
case GL_INT_IMAGE_1D :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_1D :
2015-03-16 21:44:33 -07:00
case GL_IMAGE_2D :
case GL_INT_IMAGE_2D :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_2D :
2015-03-16 21:44:33 -07:00
case GL_IMAGE_3D :
case GL_INT_IMAGE_3D :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_3D :
2015-03-16 21:44:33 -07:00
case GL_IMAGE_CUBE :
case GL_INT_IMAGE_CUBE :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_CUBE :
2015-05-28 15:27:00 -07:00
return UniformType : : Int1 ;
2012-07-08 19:10:07 -07:00
} ;
2014-04-26 23:48:41 -07:00
BX_CHECK ( false , " Unrecognized GL type 0x%04x. " , _type ) ;
2012-10-27 21:34:41 -07:00
return UniformType : : End ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
void ProgramGL : : create ( const ShaderGL & _vsh , const ShaderGL & _fsh )
2012-07-08 19:10:07 -07:00
{
m_id = glCreateProgram ( ) ;
2015-04-09 20:36:52 -07:00
BX_TRACE ( " Program create: GL%d: GL%d, GL%d " , m_id , _vsh . m_id , _fsh . m_id ) ;
2012-07-08 19:10:07 -07:00
2014-05-10 20:51:44 -07:00
const uint64_t id = ( uint64_t ( _vsh . m_hash ) < < 32 ) | _fsh . m_hash ;
2014-05-26 14:09:26 -07:00
const bool cached = s_renderGL - > programFetchFromCache ( m_id , id ) ;
2012-07-08 19:10:07 -07:00
if ( ! cached )
{
2015-04-09 20:36:52 -07:00
GLint linked = 0 ;
2015-04-09 22:31:26 -07:00
if ( 0 ! = _vsh . m_id )
2014-07-20 20:27:13 -07:00
{
2015-04-09 20:36:52 -07:00
GL_CHECK ( glAttachShader ( m_id , _vsh . m_id ) ) ;
2014-07-20 20:27:13 -07:00
2015-04-09 20:36:52 -07:00
if ( 0 ! = _fsh . m_id )
{
GL_CHECK ( glAttachShader ( m_id , _fsh . m_id ) ) ;
}
2012-07-08 19:10:07 -07:00
2015-04-09 20:36:52 -07:00
GL_CHECK ( glLinkProgram ( m_id ) ) ;
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 ) ;
}
}
2012-07-08 19:10:07 -07:00
if ( 0 = = linked )
{
2015-04-09 20:36:52 -07:00
BX_WARN ( 0 ! = _vsh . m_id , " Invalid vertex/compute shader. " ) ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glDeleteProgram ( m_id ) ) ;
2015-04-09 20:36:52 -07:00
m_used [ 0 ] = Attrib : : Count ;
m_id = 0 ;
2012-07-08 19:10:07 -07:00
return ;
}
2014-05-26 14:09:26 -07:00
s_renderGL - > programCache ( m_id , id ) ;
2012-07-08 19:10:07 -07:00
}
init ( ) ;
2013-12-13 23:52:35 -08:00
if ( ! cached )
{
// Must be after init, otherwise init might fail to lookup shader
// info (NVIDIA Tegra 3 OpenGL ES 2.0 14.01003).
GL_CHECK ( glDetachShader ( m_id , _vsh . m_id ) ) ;
2014-07-20 20:27:13 -07:00
if ( 0 ! = _fsh . m_id )
{
GL_CHECK ( glDetachShader ( m_id , _fsh . m_id ) ) ;
}
2013-12-13 23:52:35 -08:00
}
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
void ProgramGL : : destroy ( )
2012-07-08 19:10:07 -07:00
{
2013-09-20 23:07:14 -07:00
if ( NULL ! = m_constantBuffer )
{
2015-09-14 15:53:33 -07:00
UniformBuffer : : destroy ( m_constantBuffer ) ;
2013-09-20 23:07:14 -07:00
m_constantBuffer = NULL ;
}
m_numPredefined = 0 ;
2013-10-03 20:39:55 -07:00
if ( 0 ! = m_id )
{
GL_CHECK ( glUseProgram ( 0 ) ) ;
GL_CHECK ( glDeleteProgram ( m_id ) ) ;
m_id = 0 ;
}
2013-01-21 23:36:47 -08:00
2014-05-26 14:09:26 -07:00
m_vcref . invalidate ( s_renderGL - > m_vaoStateCache ) ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
void ProgramGL : : init ( )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
GLint activeAttribs = 0 ;
GLint activeUniforms = 0 ;
GLint activeBuffers = 0 ;
2012-07-08 19:10:07 -07:00
2013-12-20 19:51:17 -08:00
# if BGFX_CONFIG_RENDERER_OPENGL >= 31
GL_CHECK ( glBindFragDataLocation ( m_id , 0 , " bgfx_FragColor " ) ) ;
# endif // BGFX_CONFIG_RENDERER_OPENGL >= 31
2015-08-28 11:17:26 -07:00
bool piqSupported = true
& & s_extension [ Extension : : ARB_program_interface_query ] . m_supported
2015-08-11 19:30:33 -07:00
& & s_extension [ Extension : : ARB_shader_storage_buffer_object ] . m_supported
2015-08-28 11:17:26 -07:00
;
2015-08-11 19:30:33 -07:00
if ( piqSupported )
2014-07-20 20:27:13 -07:00
{
GL_CHECK ( glGetProgramInterfaceiv ( m_id , GL_PROGRAM_INPUT , GL_ACTIVE_RESOURCES , & activeAttribs ) ) ;
GL_CHECK ( glGetProgramInterfaceiv ( m_id , GL_UNIFORM , GL_ACTIVE_RESOURCES , & activeUniforms ) ) ;
GL_CHECK ( glGetProgramInterfaceiv ( m_id , GL_BUFFER_VARIABLE , GL_ACTIVE_RESOURCES , & activeBuffers ) ) ;
}
else
{
GL_CHECK ( glGetProgramiv ( m_id , GL_ACTIVE_ATTRIBUTES , & activeAttribs ) ) ;
GL_CHECK ( glGetProgramiv ( m_id , GL_ACTIVE_UNIFORMS , & activeUniforms ) ) ;
}
2012-07-08 19:10:07 -07:00
2014-03-16 22:36:53 -07:00
GLint max0 , max1 ;
GL_CHECK ( glGetProgramiv ( m_id , GL_ACTIVE_ATTRIBUTE_MAX_LENGTH , & max0 ) ) ;
2014-07-20 20:27:13 -07:00
GL_CHECK ( glGetProgramiv ( m_id , GL_ACTIVE_UNIFORM_MAX_LENGTH , & max1 ) ) ;
2014-03-16 22:36:53 -07:00
uint32_t maxLength = bx : : uint32_max ( max0 , max1 ) ;
2013-12-13 23:52:35 -08:00
char * name = ( char * ) alloca ( maxLength + 1 ) ;
2012-07-08 19:10:07 -07:00
BX_TRACE ( " Program %d " , m_id ) ;
2013-12-13 23:52:35 -08:00
BX_TRACE ( " Attributes (%d): " , activeAttribs ) ;
2012-07-08 19:10:07 -07:00
for ( int32_t ii = 0 ; ii < activeAttribs ; + + ii )
{
GLint size ;
GLenum type ;
GL_CHECK ( glGetActiveAttrib ( m_id , ii , maxLength + 1 , NULL , & size , & type , name ) ) ;
2013-12-13 23:52:35 -08:00
2012-07-08 19:10:07 -07:00
BX_TRACE ( " \t %s %s is at location %d "
, glslTypeName ( type )
, name
, glGetAttribLocation ( m_id , name )
) ;
}
m_numPredefined = 0 ;
m_numSamplers = 0 ;
2013-12-13 23:52:35 -08:00
BX_TRACE ( " Uniforms (%d): " , activeUniforms ) ;
2012-07-08 19:10:07 -07:00
for ( int32_t ii = 0 ; ii < activeUniforms ; + + ii )
{
2015-03-29 22:40:35 -07:00
struct VariableInfo
{
GLenum type ;
GLint loc ;
GLint num ;
} ;
VariableInfo vi ;
GLenum props [ ] = { GL_TYPE , GL_LOCATION , GL_ARRAY_SIZE } ;
2012-07-08 19:10:07 -07:00
GLenum gltype ;
2014-07-24 21:30:57 -07:00
GLint num ;
GLint loc ;
2015-08-11 19:30:33 -07:00
if ( piqSupported )
2014-07-24 21:30:57 -07:00
{
GL_CHECK ( glGetProgramResourceiv ( m_id
, GL_UNIFORM
, ii
, BX_COUNTOF ( props )
, props
, BX_COUNTOF ( props )
, NULL
, ( GLint * ) & vi
) ) ;
GL_CHECK ( glGetProgramResourceName ( m_id
, GL_UNIFORM
, ii
, maxLength + 1
, NULL
, name
) ) ;
gltype = vi . type ;
loc = vi . loc ;
num = vi . num ;
}
else
{
GL_CHECK ( glGetActiveUniform ( m_id , ii , maxLength + 1 , NULL , & num , & gltype , name ) ) ;
loc = glGetUniformLocation ( m_id , name ) ;
}
2012-07-08 19:10:07 -07:00
2014-07-24 21:30:57 -07:00
num = bx : : uint32_max ( num , 1 ) ;
2012-07-08 19:10:07 -07:00
int offset = 0 ;
char * array = strchr ( name , ' [ ' ) ;
if ( NULL ! = array )
{
BX_TRACE ( " --- %s " , name ) ;
* array = ' \0 ' ;
array + + ;
char * end = strchr ( array , ' ] ' ) ;
2015-05-21 17:49:02 -07:00
if ( NULL ! = end )
{ // Some devices (Amazon Fire) might not return terminating brace.
* end = ' \0 ' ;
offset = atoi ( array ) ;
}
2012-07-08 19:10:07 -07:00
}
2014-02-23 11:21:23 -08:00
switch ( gltype )
{
case GL_SAMPLER_2D :
2015-03-16 21:44:33 -07:00
case GL_INT_SAMPLER_2D :
case GL_UNSIGNED_INT_SAMPLER_2D :
2014-02-23 11:21:23 -08:00
case GL_SAMPLER_3D :
2015-03-16 21:44:33 -07:00
case GL_INT_SAMPLER_3D :
case GL_UNSIGNED_INT_SAMPLER_3D :
2014-02-23 11:21:23 -08:00
case GL_SAMPLER_CUBE :
2015-03-16 21:44:33 -07:00
case GL_INT_SAMPLER_CUBE :
case GL_UNSIGNED_INT_SAMPLER_CUBE :
2014-02-23 11:21:23 -08:00
case GL_SAMPLER_2D_SHADOW :
2015-03-16 21:44:33 -07:00
2014-07-20 20:27:13 -07:00
case GL_IMAGE_1D :
2015-03-16 21:44:33 -07:00
case GL_INT_IMAGE_1D :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_1D :
2015-03-16 21:44:33 -07:00
case GL_IMAGE_2D :
case GL_INT_IMAGE_2D :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_2D :
2015-03-16 21:44:33 -07:00
case GL_IMAGE_3D :
case GL_INT_IMAGE_3D :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_3D :
2015-03-16 21:44:33 -07:00
case GL_IMAGE_CUBE :
case GL_INT_IMAGE_CUBE :
2015-02-19 20:06:02 -08:00
case GL_UNSIGNED_INT_IMAGE_CUBE :
2016-03-02 08:40:05 -08:00
if ( m_numSamplers < BX_COUNTOF ( m_sampler ) )
{
BX_TRACE ( " Sampler #%d at location %d. " , m_numSamplers , loc ) ;
m_sampler [ m_numSamplers ] = loc ;
m_numSamplers + + ;
}
else
{
BX_TRACE ( " Too many samplers (max: %d)! Sampler at location %d. "
, BX_COUNTOF ( m_sampler )
, loc
) ;
}
2014-02-23 11:21:23 -08:00
break ;
default :
break ;
}
2012-07-08 19:10:07 -07:00
PredefinedUniform : : Enum predefined = nameToPredefinedUniformEnum ( name ) ;
if ( PredefinedUniform : : Count ! = predefined )
{
2015-04-07 17:58:14 -07:00
m_predefined [ m_numPredefined ] . m_loc = loc ;
m_predefined [ m_numPredefined ] . m_count = uint16_t ( num ) ;
m_predefined [ m_numPredefined ] . m_type = uint8_t ( predefined ) ;
2012-07-08 19:10:07 -07:00
m_numPredefined + + ;
}
else
{
2014-05-26 14:09:26 -07:00
const UniformInfo * info = s_renderGL - > m_uniformReg . find ( name ) ;
2015-09-25 21:51:30 -07:00
BX_WARN ( NULL ! = info , " User defined uniform '%s' is not found, it won't be set. " , name ) ;
2012-07-08 19:10:07 -07:00
if ( NULL ! = info )
{
2014-10-08 19:36:59 -07:00
if ( NULL = = m_constantBuffer )
{
2015-09-14 15:53:33 -07:00
m_constantBuffer = UniformBuffer : : create ( 1024 ) ;
2014-10-08 19:36:59 -07:00
}
2012-10-27 21:34:41 -07:00
UniformType : : Enum type = convertGlType ( gltype ) ;
2015-04-07 17:58:14 -07:00
m_constantBuffer - > writeUniformHandle ( type , 0 , info - > m_handle , uint16_t ( num ) ) ;
2012-12-29 13:46:25 -08:00
m_constantBuffer - > write ( loc ) ;
2014-04-15 19:10:56 -07:00
BX_TRACE ( " store %s %d " , name , info - > m_handle ) ;
2012-07-08 19:10:07 -07:00
}
}
2014-04-15 19:10:56 -07:00
BX_TRACE ( " \t uniform %s %s%s is at location %d, size %d, offset %d "
2012-07-08 19:10:07 -07:00
, glslTypeName ( gltype )
, name
, PredefinedUniform : : Count ! = predefined ? " * " : " "
, loc
, num
, offset
) ;
2013-04-24 08:44:55 -07:00
BX_UNUSED ( offset ) ;
2012-07-08 19:10:07 -07:00
}
2014-10-08 19:36:59 -07:00
if ( NULL ! = m_constantBuffer )
{
m_constantBuffer - > finish ( ) ;
}
2015-08-11 19:30:33 -07:00
if ( piqSupported )
2014-07-20 20:27:13 -07:00
{
struct VariableInfo
{
GLenum type ;
} ;
VariableInfo vi ;
GLenum props [ ] = { GL_TYPE } ;
BX_TRACE ( " Buffers (%d): " , activeBuffers ) ;
for ( int32_t ii = 0 ; ii < activeBuffers ; + + ii )
{
GL_CHECK ( glGetProgramResourceiv ( m_id
, GL_BUFFER_VARIABLE
, ii
, BX_COUNTOF ( props )
, props
, BX_COUNTOF ( props )
, NULL
, ( GLint * ) & vi
) ) ;
GL_CHECK ( glGetProgramResourceName ( m_id
, GL_BUFFER_VARIABLE
, ii
, maxLength + 1
, NULL
, name
) ) ;
BX_TRACE ( " \t %s %s at %d "
, glslTypeName ( vi . type )
, name
, 0 //vi.loc
) ;
}
}
2012-07-08 19:10:07 -07:00
memset ( m_attributes , 0xff , sizeof ( m_attributes ) ) ;
uint32_t used = 0 ;
2015-04-07 17:58:14 -07:00
for ( uint8_t ii = 0 ; ii < Attrib : : Count ; + + ii )
2012-07-08 19:10:07 -07:00
{
2012-12-29 13:46:25 -08:00
GLint loc = glGetAttribLocation ( m_id , s_attribName [ ii ] ) ;
if ( - 1 ! = loc )
2012-07-08 19:10:07 -07:00
{
BX_TRACE ( " attr %s: %d " , s_attribName [ ii ] , loc ) ;
m_attributes [ ii ] = loc ;
m_used [ used + + ] = ii ;
}
}
2015-07-17 11:12:41 -07:00
BX_CHECK ( used < BX_COUNTOF ( m_used ) , " Out of bounds %d > array size %d. "
, used
, BX_COUNTOF ( m_used )
) ;
2012-07-08 19:10:07 -07:00
m_used [ used ] = Attrib : : Count ;
used = 0 ;
2013-08-06 21:04:28 -07:00
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( s_instanceDataName ) ; + + ii )
2012-07-08 19:10:07 -07:00
{
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 ;
}
}
2015-07-17 11:12:41 -07:00
BX_CHECK ( used < BX_COUNTOF ( m_instanceData ) , " Out of bounds %d > array size %d. "
, used
, BX_COUNTOF ( m_instanceData )
) ;
2012-07-08 19:10:07 -07:00
m_instanceData [ used ] = 0xffff ;
}
2014-05-26 14:09:26 -07:00
void ProgramGL : : bindAttributes ( const VertexDecl & _vertexDecl , uint32_t _baseVertex ) const
2012-07-08 19:10:07 -07:00
{
for ( uint32_t ii = 0 ; Attrib : : Count ! = m_used [ ii ] ; + + ii )
{
Attrib : : Enum attr = Attrib : : Enum ( m_used [ ii ] ) ;
2012-12-29 13:46:25 -08:00
GLint loc = m_attributes [ attr ] ;
2012-07-08 19:10:07 -07:00
uint8_t num ;
AttribType : : Enum type ;
bool normalized ;
2012-12-31 18:48:52 -08:00
bool asInt ;
_vertexDecl . decode ( attr , num , type , normalized , asInt ) ;
2012-07-08 19:10:07 -07:00
2013-10-23 21:18:01 -07:00
if ( - 1 ! = loc )
2012-07-08 19:10:07 -07:00
{
2015-08-07 11:37:52 -07:00
if ( UINT16_MAX ! = _vertexDecl . m_attributes [ attr ] )
2012-07-08 19:10:07 -07:00
{
2013-10-23 21:18:01 -07:00
GL_CHECK ( glEnableVertexAttribArray ( loc ) ) ;
2014-03-04 22:20:37 -08:00
GL_CHECK ( glVertexAttribDivisor ( loc , 0 ) ) ;
2012-07-08 19:10:07 -07:00
2013-10-23 21:18:01 -07:00
uint32_t baseVertex = _baseVertex * _vertexDecl . m_stride + _vertexDecl . m_offset [ attr ] ;
2015-09-04 19:49:42 -07:00
if ( ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL > = 30 ) | | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 ) )
& & ( AttribType : : Uint8 = = type | | AttribType : : Int16 = = type )
& & ! normalized )
{
GL_CHECK ( glVertexAttribIPointer ( loc
, num
, s_attribType [ type ]
, _vertexDecl . m_stride
, ( void * ) ( uintptr_t ) baseVertex )
) ;
}
else
{
GL_CHECK ( glVertexAttribPointer ( loc
, num
, s_attribType [ type ]
, normalized
, _vertexDecl . m_stride
, ( void * ) ( uintptr_t ) baseVertex )
) ;
}
2013-10-23 21:18:01 -07:00
}
else
{
GL_CHECK ( glDisableVertexAttribArray ( loc ) ) ;
2012-07-08 19:10:07 -07:00
}
}
}
}
2014-05-26 14:09:26 -07:00
void ProgramGL : : bindInstanceData ( uint32_t _stride , uint32_t _baseVertex ) const
2012-07-08 19:10:07 -07:00
{
uint32_t baseVertex = _baseVertex ;
for ( uint32_t ii = 0 ; 0xffff ! = m_instanceData [ ii ] ; + + ii )
{
2012-12-29 13:46:25 -08:00
GLint loc = m_instanceData [ ii ] ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glEnableVertexAttribArray ( loc ) ) ;
GL_CHECK ( glVertexAttribPointer ( loc , 4 , GL_FLOAT , GL_FALSE , _stride , ( void * ) ( uintptr_t ) baseVertex ) ) ;
2014-03-04 22:20:37 -08:00
GL_CHECK ( glVertexAttribDivisor ( loc , 1 ) ) ;
2012-07-08 19:10:07 -07:00
baseVertex + = 16 ;
}
}
2014-05-26 14:09:26 -07:00
void IndexBufferGL : : destroy ( )
2013-01-21 23:36:47 -08:00
{
GL_CHECK ( glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ) ;
GL_CHECK ( glDeleteBuffers ( 1 , & m_id ) ) ;
2014-05-26 14:09:26 -07:00
m_vcref . invalidate ( s_renderGL - > m_vaoStateCache ) ;
2013-01-21 23:36:47 -08:00
}
2014-05-26 14:09:26 -07:00
void VertexBufferGL : : destroy ( )
2013-01-21 23:36:47 -08:00
{
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ) ;
GL_CHECK ( glDeleteBuffers ( 1 , & m_id ) ) ;
2014-05-26 14:09:26 -07:00
m_vcref . invalidate ( s_renderGL - > m_vaoStateCache ) ;
2013-01-21 23:36:47 -08:00
}
2013-09-08 21:03:03 -07:00
static void texImage ( GLenum _target , GLint _level , GLint _internalFormat , GLsizei _width , GLsizei _height , GLsizei _depth , GLint _border , GLenum _format , GLenum _type , const GLvoid * _data )
2012-11-03 21:36:17 -07:00
{
if ( _target = = GL_TEXTURE_3D )
{
2013-09-08 21:03:03 -07:00
GL_CHECK ( glTexImage3D ( _target , _level , _internalFormat , _width , _height , _depth , _border , _format , _type , _data ) ) ;
2012-11-03 21:36:17 -07:00
}
else
{
BX_UNUSED ( _depth ) ;
2013-09-08 21:03:03 -07:00
GL_CHECK ( glTexImage2D ( _target , _level , _internalFormat , _width , _height , _border , _format , _type , _data ) ) ;
}
}
static void texSubImage ( GLenum _target , GLint _level , GLint _xoffset , GLint _yoffset , GLint _zoffset , GLsizei _width , GLsizei _height , GLsizei _depth , GLenum _format , GLenum _type , const GLvoid * _data )
{
if ( _target = = GL_TEXTURE_3D )
{
GL_CHECK ( glTexSubImage3D ( _target , _level , _xoffset , _yoffset , _zoffset , _width , _height , _depth , _format , _type , _data ) ) ;
}
else
{
BX_UNUSED ( _zoffset , _depth ) ;
GL_CHECK ( glTexSubImage2D ( _target , _level , _xoffset , _yoffset , _width , _height , _format , _type , _data ) ) ;
2012-11-03 21:36:17 -07:00
}
}
static void compressedTexImage ( GLenum _target , GLint _level , GLenum _internalformat , GLsizei _width , GLsizei _height , GLsizei _depth , GLint _border , GLsizei _imageSize , const GLvoid * _data )
{
if ( _target = = GL_TEXTURE_3D )
{
2013-09-08 21:03:03 -07:00
GL_CHECK ( glCompressedTexImage3D ( _target , _level , _internalformat , _width , _height , _depth , _border , _imageSize , _data ) ) ;
2012-11-03 21:36:17 -07:00
}
else
{
BX_UNUSED ( _depth ) ;
2013-09-08 21:03:03 -07:00
GL_CHECK ( glCompressedTexImage2D ( _target , _level , _internalformat , _width , _height , _border , _imageSize , _data ) ) ;
2012-11-03 21:36:17 -07:00
}
}
2013-09-08 21:03:03 -07:00
static void compressedTexSubImage ( GLenum _target , GLint _level , GLint _xoffset , GLint _yoffset , GLint _zoffset , GLsizei _width , GLsizei _height , GLsizei _depth , GLenum _format , GLsizei _imageSize , const GLvoid * _data )
{
if ( _target = = GL_TEXTURE_3D )
{
GL_CHECK ( glCompressedTexSubImage3D ( _target , _level , _xoffset , _yoffset , _zoffset , _width , _height , _depth , _format , _imageSize , _data ) ) ;
}
else
{
BX_UNUSED ( _zoffset , _depth ) ;
GL_CHECK ( glCompressedTexSubImage2D ( _target , _level , _xoffset , _yoffset , _width , _height , _format , _imageSize , _data ) ) ;
}
}
2016-02-22 17:32:20 -08:00
bool TextureGL : : init ( GLenum _target , uint32_t _width , uint32_t _height , uint32_t _depth , uint8_t _numMips , uint32_t _flags )
2013-04-15 20:59:01 -07:00
{
2015-05-18 20:24:37 -07:00
m_target = _target ;
2013-07-24 21:59:59 -07:00
m_numMips = _numMips ;
2015-05-18 20:24:37 -07:00
m_flags = _flags ;
m_width = _width ;
m_height = _height ;
m_depth = _depth ;
2016-02-22 17:32:20 -08:00
m_currentSamplerHash = UINT32_MAX ;
2013-04-15 20:59:01 -07:00
2016-01-12 17:11:16 -08:00
const bool writeOnly = 0 ! = ( m_flags & BGFX_TEXTURE_RT_WRITE_ONLY ) ;
2015-04-22 15:11:45 -07:00
const bool computeWrite = 0 ! = ( m_flags & BGFX_TEXTURE_COMPUTE_WRITE ) ;
2013-04-15 20:59:01 -07:00
2016-01-12 17:11:16 -08:00
if ( ! writeOnly )
2014-02-05 23:07:11 -08:00
{
GL_CHECK ( glGenTextures ( 1 , & m_id ) ) ;
BX_CHECK ( 0 ! = m_id , " Failed to generate texture id. " ) ;
GL_CHECK ( glBindTexture ( _target , m_id ) ) ;
2013-09-08 21:03:03 -07:00
2016-02-22 17:32:20 -08:00
const TextureFormatInfo & tfi = s_textureFormat [ m_textureFormat ] ;
2015-03-28 21:25:40 -07:00
m_fmt = tfi . m_fmt ;
2013-09-08 21:03:03 -07:00
m_type = tfi . m_type ;
2014-02-05 23:07:11 -08:00
2015-04-11 09:42:17 -07:00
const bool swizzle = true
& & TextureFormat : : BGRA8 = = m_requestedFormat
& & ! s_textureFormat [ m_requestedFormat ] . m_supported
& & ! s_renderGL - > m_textureSwizzleSupport
;
2016-02-22 17:32:20 -08:00
const bool convert = false
| | m_textureFormat ! = m_requestedFormat
2015-04-11 09:42:17 -07:00
| | swizzle
;
2014-02-05 23:07:11 -08:00
2015-04-11 00:17:49 -07:00
if ( convert )
2014-02-05 23:07:11 -08:00
{
2015-04-11 00:17:49 -07:00
m_textureFormat = ( uint8_t ) TextureFormat : : RGBA8 ;
const TextureFormatInfo & tfiRgba8 = s_textureFormat [ TextureFormat : : RGBA8 ] ;
m_fmt = tfiRgba8 . m_fmt ;
m_type = tfiRgba8 . m_type ;
2014-02-05 23:07:11 -08:00
}
2013-09-08 21:03:03 -07:00
2015-04-22 15:11:45 -07:00
if ( computeWrite )
{
2015-05-18 20:24:37 -07:00
if ( _target = = GL_TEXTURE_3D )
{
GL_CHECK ( glTexStorage3D ( _target
, _numMips
, s_textureFormat [ m_textureFormat ] . m_internalFmt
, m_width
, m_height
, _depth
) ) ;
}
else
{
GL_CHECK ( glTexStorage2D ( _target
, _numMips
, s_textureFormat [ m_textureFormat ] . m_internalFmt
, m_width
, m_height
) ) ;
}
2015-04-22 15:11:45 -07:00
}
2015-09-16 17:21:28 -07:00
setSamplerState ( _flags , NULL ) ;
2015-03-28 21:25:40 -07:00
2014-03-31 22:41:56 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
2015-04-11 00:17:49 -07:00
& & TextureFormat : : BGRA8 = = m_requestedFormat
& & ! s_textureFormat [ m_requestedFormat ] . m_supported
2014-05-26 14:09:26 -07:00
& & s_renderGL - > m_textureSwizzleSupport )
2014-02-05 23:07:11 -08:00
{
GLint swizzleMask [ ] = { GL_BLUE , GL_GREEN , GL_RED , GL_ALPHA } ;
GL_CHECK ( glTexParameteriv ( GL_TEXTURE_2D , GL_TEXTURE_SWIZZLE_RGBA , swizzleMask ) ) ;
}
}
const bool renderTarget = 0 ! = ( m_flags & BGFX_TEXTURE_RT_MASK ) ;
if ( renderTarget )
2013-09-08 21:03:03 -07:00
{
2014-02-05 23:07:11 -08:00
uint32_t msaaQuality = ( ( m_flags & BGFX_TEXTURE_RT_MSAA_MASK ) > > BGFX_TEXTURE_RT_MSAA_SHIFT ) ;
msaaQuality = bx : : uint32_satsub ( msaaQuality , 1 ) ;
2014-05-26 14:09:26 -07:00
msaaQuality = bx : : uint32_min ( s_renderGL - > m_maxMsaa , msaaQuality = = 0 ? 0 : 1 < < msaaQuality ) ;
2014-02-05 23:07:11 -08:00
if ( 0 ! = msaaQuality
2016-01-12 17:11:16 -08:00
| | writeOnly )
2014-02-05 23:07:11 -08:00
{
GL_CHECK ( glGenRenderbuffers ( 1 , & m_rbo ) ) ;
BX_CHECK ( 0 ! = m_rbo , " Failed to generate renderbuffer id. " ) ;
GL_CHECK ( glBindRenderbuffer ( GL_RENDERBUFFER , m_rbo ) ) ;
if ( 0 = = msaaQuality )
{
GL_CHECK ( glRenderbufferStorage ( GL_RENDERBUFFER
2015-03-01 12:33:27 -08:00
, s_rboFormat [ m_textureFormat ]
2014-02-05 23:07:11 -08:00
, _width
, _height
) ) ;
}
2014-03-29 23:12:15 -07:00
else if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
2014-02-05 23:07:11 -08:00
{
GL_CHECK ( glRenderbufferStorageMultisample ( GL_RENDERBUFFER
, msaaQuality
2015-03-01 12:33:27 -08:00
, s_rboFormat [ m_textureFormat ]
2014-02-05 23:07:11 -08:00
, _width
, _height
) ) ;
}
GL_CHECK ( glBindRenderbuffer ( GL_RENDERBUFFER , 0 ) ) ;
2016-01-12 17:11:16 -08:00
if ( writeOnly )
2014-02-05 23:07:11 -08:00
{
// This is render buffer, there is no sampling, no need
// to create texture.
return false ;
}
}
2013-09-08 21:03:03 -07:00
}
2014-02-05 23:07:11 -08:00
return true ;
2013-04-15 20:59:01 -07:00
}
2014-05-26 14:09:26 -07:00
void TextureGL : : create ( const Memory * _mem , uint32_t _flags , uint8_t _skip )
2012-07-08 19:10:07 -07:00
{
2013-09-02 16:22:53 -07:00
ImageContainer imageContainer ;
2012-07-08 19:10:07 -07:00
2013-09-02 16:22:53 -07:00
if ( imageParse ( imageContainer , _mem - > data , _mem - > size ) )
2012-07-08 19:10:07 -07:00
{
2013-09-02 16:22:53 -07:00
uint8_t numMips = imageContainer . m_numMips ;
2015-04-07 17:58:14 -07:00
const uint8_t startLod = uint8_t ( bx : : uint32_min ( _skip , numMips - 1 ) ) ;
numMips - = startLod ;
2015-04-26 15:23:33 -07:00
uint32_t textureWidth ;
uint32_t textureHeight ;
2015-05-18 20:24:37 -07:00
uint32_t textureDepth ;
2015-04-26 15:23:33 -07:00
{
const ImageBlockInfo & ibi = getBlockInfo ( TextureFormat : : Enum ( imageContainer . m_format ) ) ;
textureWidth = bx : : uint32_max ( ibi . blockWidth , imageContainer . m_width > > startLod ) ;
textureHeight = bx : : uint32_max ( ibi . blockHeight , imageContainer . m_height > > startLod ) ;
2015-05-18 20:24:37 -07:00
textureDepth = imageContainer . m_depth ;
2015-04-26 15:23:33 -07:00
}
2012-07-08 19:10:07 -07:00
2016-02-22 17:32:20 -08:00
m_requestedFormat = uint8_t ( imageContainer . m_format ) ;
m_textureFormat = uint8_t ( getViableTextureFormat ( imageContainer ) ) ;
2013-09-08 21:03:03 -07:00
GLenum target = GL_TEXTURE_2D ;
2013-09-02 16:22:53 -07:00
if ( imageContainer . m_cubeMap )
2012-07-08 19:10:07 -07:00
{
2013-09-08 21:03:03 -07:00
target = GL_TEXTURE_CUBE_MAP ;
2012-07-08 19:10:07 -07:00
}
2013-09-02 16:22:53 -07:00
else if ( imageContainer . m_depth > 1 )
2012-07-08 19:10:07 -07:00
{
2013-09-08 21:03:03 -07:00
target = GL_TEXTURE_3D ;
2012-07-08 19:10:07 -07:00
}
2014-02-05 23:07:11 -08:00
if ( ! init ( target
2014-02-19 22:34:53 -08:00
, textureWidth
, textureHeight
2015-05-18 20:24:37 -07:00
, textureDepth
2014-02-05 23:07:11 -08:00
, numMips
, _flags
) )
{
return ;
}
2012-07-08 19:10:07 -07:00
2015-04-22 15:11:45 -07:00
const bool computeWrite = 0 ! = ( m_flags & BGFX_TEXTURE_COMPUTE_WRITE ) ;
2015-05-05 16:34:13 -07:00
const bool srgb = 0 ! = ( m_flags & BGFX_TEXTURE_SRGB ) ;
2015-04-22 15:11:45 -07:00
2013-09-08 21:03:03 -07:00
target = GL_TEXTURE_CUBE_MAP = = m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target ;
2012-12-30 20:52:47 -08:00
2015-05-05 16:34:13 -07:00
const GLenum internalFmt = srgb
? s_textureFormat [ m_textureFormat ] . m_internalFmtSrgb
: s_textureFormat [ m_textureFormat ] . m_internalFmt
;
2013-01-14 20:10:07 -08:00
2014-02-16 10:50:58 -08:00
const bool swizzle = true
2015-04-11 00:17:49 -07:00
& & TextureFormat : : BGRA8 = = m_requestedFormat
& & ! s_textureFormat [ m_requestedFormat ] . m_supported
2014-05-26 14:09:26 -07:00
& & ! s_renderGL - > m_textureSwizzleSupport
2014-02-16 10:50:58 -08:00
;
2015-04-11 00:17:49 -07:00
const bool compressed = isCompressed ( TextureFormat : : Enum ( m_requestedFormat ) ) ;
const bool convert = false
2015-04-26 15:23:33 -07:00
| | m_textureFormat ! = m_requestedFormat
2015-04-11 00:17:49 -07:00
| | swizzle
;
2013-01-14 20:10:07 -08:00
2015-03-16 21:44:33 -07:00
BX_TRACE ( " Texture%-4s %3d: %s (requested: %s), %dx%dx%d%s. "
, imageContainer . m_cubeMap ? " Cube " : ( 1 < imageContainer . m_depth ? " 3D " : " 2D " )
2014-05-26 14:09:26 -07:00
, this - s_renderGL - > m_textures
2014-04-19 15:02:43 -07:00
, getName ( ( TextureFormat : : Enum ) m_textureFormat )
, getName ( ( TextureFormat : : Enum ) m_requestedFormat )
, textureWidth
, textureHeight
2015-03-16 21:44:33 -07:00
, imageContainer . m_cubeMap ? 6 : ( 1 < imageContainer . m_depth ? imageContainer . m_depth : 0 )
2014-04-19 15:02:43 -07:00
, 0 ! = ( m_flags & BGFX_TEXTURE_RT_MASK ) ? " (render target) " : " "
) ;
2015-04-11 00:17:49 -07:00
BX_WARN ( ! convert , " Texture %s%s%s from %s to %s. "
2014-02-14 20:43:00 -08:00
, swizzle ? " swizzle " : " "
, swizzle & & convert ? " and " : " "
, convert ? " convert " : " "
, getName ( ( TextureFormat : : Enum ) m_requestedFormat )
, getName ( ( TextureFormat : : Enum ) m_textureFormat )
) ;
2013-09-08 21:03:03 -07:00
uint8_t * temp = NULL ;
2015-04-11 00:17:49 -07:00
if ( convert )
2013-09-08 21:03:03 -07:00
{
2014-02-19 22:34:53 -08:00
temp = ( uint8_t * ) BX_ALLOC ( g_allocator , textureWidth * textureHeight * 4 ) ;
2013-09-08 21:03:03 -07:00
}
2012-07-08 19:10:07 -07:00
2013-09-08 21:03:03 -07:00
for ( uint8_t side = 0 , numSides = imageContainer . m_cubeMap ? 6 : 1 ; side < numSides ; + + side )
{
2014-02-19 22:34:53 -08:00
uint32_t width = textureWidth ;
uint32_t height = textureHeight ;
2013-09-08 21:03:03 -07:00
uint32_t depth = imageContainer . m_depth ;
2012-07-08 19:10:07 -07:00
2015-04-07 17:58:14 -07:00
for ( uint8_t lod = 0 , num = numMips ; lod < num ; + + lod )
2012-07-08 19:10:07 -07:00
{
2015-04-26 15:23:33 -07:00
width = bx : : uint32_max ( 1 , width ) ;
height = bx : : uint32_max ( 1 , height ) ;
2013-09-08 21:03:03 -07:00
depth = bx : : uint32_max ( 1 , depth ) ;
2012-07-08 19:10:07 -07:00
2013-09-08 21:03:03 -07:00
ImageMip mip ;
2014-02-19 22:34:53 -08:00
if ( imageGetRawData ( imageContainer , side , lod + startLod , _mem - > data , _mem - > size , mip ) )
2012-07-08 19:10:07 -07:00
{
2015-04-26 15:23:33 -07:00
if ( compressed
& & ! convert )
2012-07-08 19:10:07 -07:00
{
2013-09-08 21:03:03 -07:00
compressedTexImage ( target + side
2012-11-03 21:36:17 -07:00
, lod
, internalFmt
, width
, height
, depth
, 0
2013-09-08 21:03:03 -07:00
, mip . m_size
, mip . m_data
2012-11-03 21:36:17 -07:00
) ;
2012-07-08 19:10:07 -07:00
}
2013-09-08 21:03:03 -07:00
else
{
const uint8_t * data = mip . m_data ;
2012-07-08 19:10:07 -07:00
2013-09-08 21:03:03 -07:00
if ( convert )
{
2015-04-26 15:23:33 -07:00
imageDecodeToRgba8 ( temp
, mip . m_data
, mip . m_width
, mip . m_height
, mip . m_width * 4
, mip . m_format
) ;
2013-09-08 21:03:03 -07:00
data = temp ;
}
2012-07-08 19:10:07 -07:00
2013-09-08 21:03:03 -07:00
texImage ( target + side
, lod
2012-11-03 21:36:17 -07:00
, internalFmt
, width
, height
, depth
, 0
2013-09-08 21:03:03 -07:00
, m_fmt
, m_type
, data
2012-11-03 21:36:17 -07:00
) ;
2012-07-08 19:10:07 -07:00
}
}
2015-04-22 15:11:45 -07:00
else if ( ! computeWrite )
2012-08-12 21:02:11 -07:00
{
2013-09-08 21:03:03 -07:00
if ( compressed )
2012-11-25 18:24:50 -08:00
{
2013-09-08 21:03:03 -07:00
uint32_t size = bx : : uint32_max ( 1 , ( width + 3 ) > > 2 )
* bx : : uint32_max ( 1 , ( height + 3 ) > > 2 )
* 4 * 4 * getBitsPerPixel ( TextureFormat : : Enum ( m_textureFormat ) ) / 8
;
2012-12-26 22:52:10 -08:00
compressedTexImage ( target + side
, lod
, internalFmt
, width
, height
, depth
, 0
, size
2013-09-08 21:03:03 -07:00
, NULL
2012-12-26 22:52:10 -08:00
) ;
2012-11-25 18:24:50 -08:00
}
else
{
2012-12-26 22:52:10 -08:00
texImage ( target + side
, lod
, internalFmt
, width
, height
, depth
, 0
, m_fmt
, m_type
2013-09-08 21:03:03 -07:00
, NULL
2012-12-26 22:52:10 -08:00
) ;
2012-11-25 18:24:50 -08:00
}
2012-08-12 21:02:11 -07:00
}
2012-07-08 19:10:07 -07:00
2013-09-08 21:03:03 -07:00
width > > = 1 ;
height > > = 1 ;
depth > > = 1 ;
2012-07-08 19:10:07 -07:00
}
}
2013-09-08 21:03:03 -07:00
if ( NULL ! = temp )
2012-07-08 19:10:07 -07:00
{
2013-09-16 21:40:30 -07:00
BX_FREE ( g_allocator , temp ) ;
2012-07-08 19:10:07 -07:00
}
}
GL_CHECK ( glBindTexture ( m_target , 0 ) ) ;
}
2014-05-26 14:09:26 -07:00
void TextureGL : : destroy ( )
2012-07-08 19:10:07 -07:00
{
2016-01-27 14:50:57 -08:00
if ( 0 = = ( m_flags & BGFX_TEXTURE_INTERNAL_SHARED )
& & 0 ! = m_id )
2012-07-08 19:10:07 -07:00
{
GL_CHECK ( glBindTexture ( m_target , 0 ) ) ;
GL_CHECK ( glDeleteTextures ( 1 , & m_id ) ) ;
m_id = 0 ;
}
2014-02-05 23:07:11 -08:00
if ( 0 ! = m_rbo )
{
GL_CHECK ( glDeleteRenderbuffers ( 1 , & m_rbo ) ) ;
m_rbo = 0 ;
}
2012-07-08 19:10:07 -07:00
}
2016-01-27 14:50:57 -08:00
void TextureGL : : overrideInternal ( uintptr_t _ptr )
{
destroy ( ) ;
m_flags | = BGFX_TEXTURE_INTERNAL_SHARED ;
m_id = ( GLuint ) _ptr ;
}
2014-05-26 14:09:26 -07:00
void TextureGL : : update ( uint8_t _side , uint8_t _mip , const Rect & _rect , uint16_t _z , uint16_t _depth , uint16_t _pitch , const Memory * _mem )
2012-08-12 21:02:11 -07:00
{
2013-09-08 21:03:03 -07:00
BX_UNUSED ( _z , _depth ) ;
2013-03-28 22:34:59 -07:00
2013-11-07 22:59:17 -08:00
const uint32_t bpp = getBitsPerPixel ( TextureFormat : : Enum ( m_textureFormat ) ) ;
const uint32_t rectpitch = _rect . m_width * bpp / 8 ;
uint32_t srcpitch = UINT16_MAX = = _pitch ? rectpitch : _pitch ;
2012-08-12 21:02:11 -07:00
GL_CHECK ( glBindTexture ( m_target , m_id ) ) ;
GL_CHECK ( glPixelStorei ( GL_UNPACK_ALIGNMENT , 1 ) ) ;
2012-08-19 18:50:23 -07:00
2013-09-08 21:03:03 -07:00
GLenum target = GL_TEXTURE_CUBE_MAP = = m_target ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : m_target ;
2014-02-16 10:50:58 -08:00
const bool swizzle = true
2015-04-11 00:17:49 -07:00
& & TextureFormat : : BGRA8 = = m_requestedFormat
& & ! s_textureFormat [ m_requestedFormat ] . m_supported
2014-05-26 14:09:26 -07:00
& & ! s_renderGL - > m_textureSwizzleSupport
2014-02-16 10:50:58 -08:00
;
2014-06-08 20:57:39 -07:00
const bool unpackRowLength = BX_IGNORE_C4127 ( ! ! BGFX_CONFIG_RENDERER_OPENGL | | s_extension [ Extension : : EXT_unpack_subimage ] . m_supported ) ;
2015-04-11 00:17:49 -07:00
const bool compressed = isCompressed ( TextureFormat : : Enum ( m_requestedFormat ) ) ;
const bool convert = false
| | ( compressed & & m_textureFormat ! = m_requestedFormat )
| | swizzle
;
2013-09-08 21:03:03 -07:00
2013-11-07 22:59:17 -08:00
const uint32_t width = _rect . m_width ;
const uint32_t height = _rect . m_height ;
2013-09-08 21:03:03 -07:00
uint8_t * temp = NULL ;
2013-11-08 20:53:23 -08:00
if ( convert
| | ! unpackRowLength )
2012-08-19 18:50:23 -07:00
{
2013-11-07 22:59:17 -08:00
temp = ( uint8_t * ) BX_ALLOC ( g_allocator , rectpitch * height ) ;
2013-09-08 21:03:03 -07:00
}
2013-11-08 20:53:23 -08:00
else if ( unpackRowLength )
{
GL_CHECK ( glPixelStorei ( GL_UNPACK_ROW_LENGTH , srcpitch * 8 / bpp ) ) ;
}
2012-08-19 18:50:23 -07:00
2013-09-08 21:03:03 -07:00
if ( compressed )
{
2013-11-08 20:53:23 -08:00
const uint8_t * data = _mem - > data ;
if ( ! unpackRowLength )
{
imageCopy ( width , height , bpp , srcpitch , data , temp ) ;
data = temp ;
}
2013-09-08 21:03:03 -07:00
GL_CHECK ( compressedTexSubImage ( target + _side
, _mip
, _rect . m_x
, _rect . m_y
, _z
, _rect . m_width
, _rect . m_height
, _depth
, m_fmt
, _mem - > size
2013-11-08 20:53:23 -08:00
, data
2013-09-08 21:03:03 -07:00
) ) ;
}
else
{
const uint8_t * data = _mem - > data ;
2012-08-19 18:50:23 -07:00
2013-09-08 21:03:03 -07:00
if ( convert )
2012-11-25 18:24:50 -08:00
{
2016-01-04 21:48:01 -08:00
imageDecodeToRgba8 ( temp , data , width , height , srcpitch , TextureFormat : : Enum ( m_requestedFormat ) ) ;
2013-09-08 21:03:03 -07:00
data = temp ;
2013-11-07 22:59:17 -08:00
srcpitch = rectpitch ;
2012-11-25 18:24:50 -08:00
}
2013-09-08 21:03:03 -07:00
2015-04-11 00:17:49 -07:00
if ( ! unpackRowLength
& & ! convert )
2013-11-08 20:53:23 -08:00
{
imageCopy ( width , height , bpp , srcpitch , data , temp ) ;
data = temp ;
}
2013-09-08 21:03:03 -07:00
GL_CHECK ( texSubImage ( target + _side
, _mip
, _rect . m_x
, _rect . m_y
, _z
, _rect . m_width
, _rect . m_height
, _depth
, m_fmt
, m_type
, data
) ) ;
}
2015-05-12 13:09:31 +10:00
if ( ! convert
& & unpackRowLength )
{
GL_CHECK ( glPixelStorei ( GL_UNPACK_ROW_LENGTH , 0 ) ) ;
}
2013-09-08 21:03:03 -07:00
if ( NULL ! = temp )
{
2013-09-16 21:40:30 -07:00
BX_FREE ( g_allocator , temp ) ;
2012-10-13 22:21:02 -07:00
}
2012-08-12 21:02:11 -07:00
}
2015-09-16 17:21:28 -07:00
void TextureGL : : setSamplerState ( uint32_t _flags , const float _rgba [ 4 ] )
2013-07-24 21:59:59 -07:00
{
2015-03-29 23:10:52 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES < 30 )
& & ! s_textureFilter [ m_textureFormat ] )
2015-03-28 21:25:40 -07:00
{
// Force point sampling when texture format doesn't support linear sampling.
2016-03-23 00:20:58 +01:00
_flags & = ~ ( 0
2015-03-28 21:25:40 -07:00
| BGFX_TEXTURE_MIN_MASK
| BGFX_TEXTURE_MAG_MASK
| BGFX_TEXTURE_MIP_MASK
2016-03-23 00:20:58 +01:00
) ;
2015-03-28 21:25:40 -07:00
_flags | = 0
| BGFX_TEXTURE_MIN_POINT
| BGFX_TEXTURE_MAG_POINT
| BGFX_TEXTURE_MIP_POINT
;
}
2015-11-01 17:28:23 -08:00
const uint32_t flags = ( 0 ! = ( BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags ) ? m_flags : _flags ) & BGFX_TEXTURE_SAMPLER_BITS_MASK ;
2015-09-16 17:21:28 -07:00
bool hasBorderColor = false ;
bx : : HashMurmur2A murmur ;
murmur . begin ( ) ;
murmur . add ( flags ) ;
if ( NULL ! = _rgba )
{
if ( BGFX_TEXTURE_U_BORDER = = ( flags & BGFX_TEXTURE_U_BORDER )
| | BGFX_TEXTURE_V_BORDER = = ( flags & BGFX_TEXTURE_V_BORDER )
| | BGFX_TEXTURE_W_BORDER = = ( flags & BGFX_TEXTURE_W_BORDER ) )
{
murmur . add ( _rgba , 16 ) ;
hasBorderColor = true ;
}
}
uint32_t hash = murmur . end ( ) ;
if ( hash ! = m_currentSamplerHash )
2013-07-24 21:59:59 -07:00
{
2015-09-16 17:21:28 -07:00
const GLenum target = m_target ;
2013-07-24 21:59:59 -07:00
const uint8_t numMips = m_numMips ;
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_WRAP_S , s_textureAddress [ ( flags & BGFX_TEXTURE_U_MASK ) > > BGFX_TEXTURE_U_SHIFT ] ) ) ;
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_WRAP_T , s_textureAddress [ ( flags & BGFX_TEXTURE_V_MASK ) > > BGFX_TEXTURE_V_SHIFT ] ) ) ;
2014-03-29 23:12:15 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
2014-03-09 21:20:34 -07:00
| | s_extension [ Extension : : APPLE_texture_max_level ] . m_supported )
{
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_MAX_LEVEL , numMips - 1 ) ) ;
}
2013-07-24 21:59:59 -07:00
if ( target = = GL_TEXTURE_3D )
{
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_WRAP_R , s_textureAddress [ ( flags & BGFX_TEXTURE_W_MASK ) > > BGFX_TEXTURE_W_SHIFT ] ) ) ;
}
2015-03-28 21:25:40 -07:00
GLenum magFilter ;
GLenum minFilter ;
getFilters ( flags , 1 < numMips , magFilter , minFilter ) ;
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , magFilter ) ) ;
2013-07-24 21:59:59 -07:00
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , minFilter ) ) ;
2015-09-11 20:05:13 -07:00
2015-09-12 09:25:37 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
| | s_renderGL - > m_borderColorSupport )
{
2015-09-16 17:21:28 -07:00
if ( hasBorderColor )
{
GL_CHECK ( glTexParameterfv ( target , GL_TEXTURE_BORDER_COLOR , _rgba ) ) ;
}
2015-09-12 09:25:37 -07:00
}
2015-09-11 20:05:13 -07:00
2014-01-08 22:08:37 -08:00
if ( 0 ! = ( flags & ( BGFX_TEXTURE_MIN_ANISOTROPIC | BGFX_TEXTURE_MAG_ANISOTROPIC ) )
2014-05-26 14:09:26 -07:00
& & 0.0f < s_renderGL - > m_maxAnisotropy )
2013-07-24 21:59:59 -07:00
{
2014-05-26 14:09:26 -07:00
GL_CHECK ( glTexParameterf ( target , GL_TEXTURE_MAX_ANISOTROPY_EXT , s_renderGL - > m_maxAnisotropy ) ) ;
2013-07-24 21:59:59 -07:00
}
2014-03-29 23:12:15 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 )
2014-05-26 14:09:26 -07:00
| | s_renderGL - > m_shadowSamplersSupport )
2014-02-23 11:21:23 -08:00
{
const uint32_t cmpFunc = ( flags & BGFX_TEXTURE_COMPARE_MASK ) > > BGFX_TEXTURE_COMPARE_SHIFT ;
if ( 0 = = cmpFunc )
{
GL_CHECK ( glTexParameteri ( m_target , GL_TEXTURE_COMPARE_MODE , GL_NONE ) ) ;
}
else
{
GL_CHECK ( glTexParameteri ( m_target , GL_TEXTURE_COMPARE_MODE , GL_COMPARE_REF_TO_TEXTURE ) ) ;
GL_CHECK ( glTexParameteri ( m_target , GL_TEXTURE_COMPARE_FUNC , s_cmpFunc [ cmpFunc ] ) ) ;
}
}
2015-09-16 17:21:28 -07:00
m_currentSamplerHash = hash ;
2013-07-24 21:59:59 -07:00
}
}
2015-09-16 17:21:28 -07:00
void TextureGL : : commit ( uint32_t _stage , uint32_t _flags , const float _palette [ ] [ 4 ] )
2013-07-24 21:59:59 -07:00
{
2015-11-01 17:28:23 -08:00
const uint32_t flags = 0 = = ( BGFX_TEXTURE_INTERNAL_DEFAULT_SAMPLER & _flags )
2015-09-16 17:21:28 -07:00
? _flags
: m_flags
;
const uint32_t index = ( flags & BGFX_TEXTURE_BORDER_COLOR_MASK ) > > BGFX_TEXTURE_BORDER_COLOR_SHIFT ;
2013-07-24 21:59:59 -07:00
GL_CHECK ( glActiveTexture ( GL_TEXTURE0 + _stage ) ) ;
GL_CHECK ( glBindTexture ( m_target , m_id ) ) ;
2014-03-31 22:41:56 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES )
& & BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES < 30 ) )
2013-07-24 21:59:59 -07:00
{
2014-02-20 23:03:31 -08:00
// GLES2 doesn't have support for sampler object.
2015-09-16 17:21:28 -07:00
setSamplerState ( flags , _palette [ index ] ) ;
2014-02-20 23:03:31 -08:00
}
2014-03-31 22:41:56 -07:00
else if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
& & BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL < 31 ) )
2014-02-20 23:03:31 -08:00
{
// In case that GL 2.1 sampler object is supported via extension.
2014-05-26 14:09:26 -07:00
if ( s_renderGL - > m_samplerObjectSupport )
2014-02-20 23:03:31 -08:00
{
2015-09-16 17:21:28 -07:00
s_renderGL - > setSamplerState ( _stage , m_numMips , flags , _palette [ index ] ) ;
2014-02-20 23:03:31 -08:00
}
else
{
2015-09-16 17:21:28 -07:00
setSamplerState ( flags , _palette [ index ] ) ;
2014-02-20 23:03:31 -08:00
}
2013-07-24 21:59:59 -07:00
}
else
{
2014-02-20 23:03:31 -08:00
// Everything else has sampler object.
2015-09-16 17:21:28 -07:00
s_renderGL - > setSamplerState ( _stage , m_numMips , flags , _palette [ index ] ) ;
2013-07-24 21:59:59 -07:00
}
}
2013-12-12 22:35:27 -08:00
void writeString ( bx : : WriterI * _writer , const char * _str )
{
2013-12-15 12:30:23 -08:00
bx : : write ( _writer , _str , ( int32_t ) strlen ( _str ) ) ;
2013-12-12 22:35:27 -08:00
}
2014-04-01 22:31:02 -07:00
void writeStringf ( bx : : WriterI * _writer , const char * _format , . . . )
{
char temp [ 512 ] ;
va_list argList ;
va_start ( argList , _format ) ;
int len = bx : : vsnprintf ( temp , BX_COUNTOF ( temp ) , _format , argList ) ;
va_end ( argList ) ;
bx : : write ( _writer , temp , len ) ;
}
2013-12-13 23:06:28 -08:00
void strins ( char * _str , const char * _insert )
{
size_t len = strlen ( _insert ) ;
2014-02-13 22:13:19 -08:00
memmove ( & _str [ len ] , _str , strlen ( _str ) + 1 ) ;
2013-12-13 23:06:28 -08:00
memcpy ( _str , _insert , len ) ;
}
2014-05-26 14:09:26 -07:00
void ShaderGL : : create ( Memory * _mem )
2013-12-12 22:35:27 -08:00
{
bx : : MemoryReader reader ( _mem - > data , _mem - > size ) ;
m_hash = bx : : hashMurmur2A ( _mem - > data , _mem - > size ) ;
uint32_t magic ;
bx : : read ( & reader , magic ) ;
2014-03-29 19:42:57 -07:00
switch ( magic )
{
2014-05-10 20:51:44 -07:00
case BGFX_CHUNK_MAGIC_CSH : m_type = GL_COMPUTE_SHADER ; break ;
case BGFX_CHUNK_MAGIC_FSH : m_type = GL_FRAGMENT_SHADER ; break ;
case BGFX_CHUNK_MAGIC_VSH : m_type = GL_VERTEX_SHADER ; break ;
2014-03-29 19:42:57 -07:00
default :
BGFX_FATAL ( false , Fatal : : InvalidShader , " Unknown shader format %x. " , magic ) ;
break ;
}
2013-12-12 22:35:27 -08:00
uint32_t iohash ;
bx : : read ( & reader , iohash ) ;
2014-04-15 19:10:56 -07:00
uint16_t count ;
bx : : read ( & reader , count ) ;
2014-07-20 20:27:13 -07:00
BX_TRACE ( " %s Shader consts %d "
, BGFX_CHUNK_MAGIC_FSH = = magic ? " Fragment " : BGFX_CHUNK_MAGIC_VSH = = magic ? " Vertex " : " Compute "
, count
) ;
2014-04-15 19:10:56 -07:00
for ( uint32_t ii = 0 ; ii < count ; + + ii )
{
2016-02-20 14:49:22 -08:00
uint8_t nameSize = 0 ;
2014-04-15 19:10:56 -07:00
bx : : read ( & reader , nameSize ) ;
char name [ 256 ] ;
bx : : read ( & reader , & name , nameSize ) ;
name [ nameSize ] = ' \0 ' ;
uint8_t type ;
bx : : read ( & reader , type ) ;
uint8_t num ;
bx : : read ( & reader , num ) ;
uint16_t regIndex ;
bx : : read ( & reader , regIndex ) ;
uint16_t regCount ;
bx : : read ( & reader , regCount ) ;
}
uint32_t shaderSize ;
bx : : read ( & reader , shaderSize ) ;
2014-03-29 19:42:57 -07:00
m_id = glCreateShader ( m_type ) ;
2014-12-25 09:27:51 -08:00
BX_WARN ( 0 ! = m_id , " Failed to create %s shader. "
, BGFX_CHUNK_MAGIC_FSH = = magic ? " fragment " : BGFX_CHUNK_MAGIC_VSH = = magic ? " vertex " : " compute "
) ;
2014-03-29 19:42:57 -07:00
2013-12-12 22:35:27 -08:00
const char * code = ( const char * ) reader . getDataPtr ( ) ;
if ( 0 ! = m_id )
{
2014-05-10 20:51:44 -07:00
if ( GL_COMPUTE_SHADER ! = m_type )
2013-12-12 22:35:27 -08:00
{
2014-05-10 20:51:44 -07:00
int32_t codeLen = ( int32_t ) strlen ( code ) ;
int32_t tempLen = codeLen + ( 4 < < 10 ) ;
char * temp = ( char * ) alloca ( tempLen ) ;
bx : : StaticMemoryBlockWriter writer ( temp , tempLen ) ;
2014-02-09 16:46:50 -08:00
2014-05-10 20:51:44 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES )
& & BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES < 30 ) )
{
2014-06-25 18:43:26 -07:00
writeString ( & writer
, " #define flat \n "
" #define smooth \n "
" #define noperspective \n "
) ;
2015-01-08 20:43:36 -08:00
bool usesDerivatives = s_extension [ Extension : : OES_standard_derivatives ] . m_supported
2014-05-10 20:51:44 -07:00
& & bx : : findIdentifierMatch ( code , s_OES_standard_derivatives )
;
2013-12-12 22:35:27 -08:00
2014-09-12 00:02:12 -07:00
bool usesFragData = ! ! bx : : findIdentifierMatch ( code , " gl_FragData " ) ;
2014-05-10 20:51:44 -07:00
bool usesFragDepth = ! ! bx : : findIdentifierMatch ( code , " gl_FragDepth " ) ;
2014-02-09 16:46:50 -08:00
2014-05-10 20:51:44 -07:00
bool usesShadowSamplers = ! ! bx : : findIdentifierMatch ( code , s_EXT_shadow_samplers ) ;
2014-02-16 16:08:44 -08:00
2014-05-10 20:51:44 -07:00
bool usesTexture3D = s_extension [ Extension : : OES_texture_3D ] . m_supported
& & bx : : findIdentifierMatch ( code , s_OES_texture_3D )
;
2014-02-09 16:46:50 -08:00
2014-05-10 20:51:44 -07:00
bool usesTextureLod = ! ! bx : : findIdentifierMatch ( code , s_EXT_shader_texture_lod ) ;
2014-02-13 22:13:19 -08:00
2014-07-29 21:29:38 -07:00
bool usesFragmentOrdering = ! ! bx : : findIdentifierMatch ( code , " beginFragmentShaderOrdering " ) ;
2014-05-10 20:51:44 -07:00
if ( usesDerivatives )
2014-02-09 16:46:50 -08:00
{
2014-05-10 20:51:44 -07:00
writeString ( & writer , " #extension GL_OES_standard_derivatives : enable \n " ) ;
2014-02-09 16:46:50 -08:00
}
2014-09-12 00:02:12 -07:00
if ( usesFragData )
{
2015-03-22 22:03:37 -07:00
BX_WARN ( s_extension [ Extension : : EXT_draw_buffers ] . m_supported
| | s_extension [ Extension : : WEBGL_draw_buffers ] . m_supported
, " EXT_draw_buffers is used but not supported by GLES2 driver. "
) ;
2014-09-12 00:02:12 -07:00
writeString ( & writer
, " #extension GL_EXT_draw_buffers : enable \n "
) ;
}
2014-05-10 20:51:44 -07:00
bool insertFragDepth = false ;
if ( usesFragDepth )
2014-02-23 11:21:23 -08:00
{
2014-05-10 20:51:44 -07:00
BX_WARN ( s_extension [ Extension : : EXT_frag_depth ] . m_supported , " EXT_frag_depth is used but not supported by GLES2 driver. " ) ;
if ( s_extension [ Extension : : EXT_frag_depth ] . m_supported )
{
writeString ( & writer
, " #extension GL_EXT_frag_depth : enable \n "
" #define bgfx_FragDepth gl_FragDepthEXT \n "
) ;
char str [ 128 ] ;
bx : : snprintf ( str , BX_COUNTOF ( str ) , " %s float gl_FragDepthEXT; \n "
, s_extension [ Extension : : OES_fragment_precision_high ] . m_supported ? " highp " : " mediump "
) ;
writeString ( & writer , str ) ;
}
else
{
insertFragDepth = true ;
}
2014-02-23 11:21:23 -08:00
}
2014-05-10 20:51:44 -07:00
if ( usesShadowSamplers )
2014-02-23 11:21:23 -08:00
{
2014-05-26 14:09:26 -07:00
if ( s_renderGL - > m_shadowSamplersSupport )
2014-05-10 20:51:44 -07:00
{
writeString ( & writer
, " #extension GL_EXT_shadow_samplers : enable \n "
" #define shadow2D shadow2DEXT \n "
" #define shadow2DProj shadow2DProjEXT \n "
) ;
}
else
{
writeString ( & writer
, " #define sampler2DShadow sampler2D \n "
" #define shadow2D(_sampler, _coord) step(_coord.z, texture2D(_sampler, _coord.xy).x) \n "
" #define shadow2DProj(_sampler, _coord) step(_coord.z/_coord.w, texture2DProj(_sampler, _coord).x) \n "
) ;
}
2014-02-23 11:21:23 -08:00
}
2013-12-12 22:35:27 -08:00
2014-05-10 20:51:44 -07:00
if ( usesTexture3D )
2014-02-16 16:08:44 -08:00
{
2014-05-10 20:51:44 -07:00
writeString ( & writer , " #extension GL_OES_texture_3D : enable \n " ) ;
2014-02-16 16:08:44 -08:00
}
2014-05-10 20:51:44 -07:00
if ( usesTextureLod )
2014-02-16 16:08:44 -08:00
{
2014-05-10 20:51:44 -07:00
BX_WARN ( s_extension [ Extension : : EXT_shader_texture_lod ] . m_supported , " EXT_shader_texture_lod is used but not supported by GLES2 driver. " ) ;
2015-07-28 20:56:41 -07:00
if ( s_extension [ Extension : : EXT_shader_texture_lod ] . m_supported
/*&& GL_VERTEX_SHADER == m_type*/ )
2014-05-10 20:51:44 -07:00
{
writeString ( & writer
, " #extension GL_EXT_shader_texture_lod : enable \n "
" #define texture2DLod texture2DLodEXT \n "
" #define texture2DProjLod texture2DProjLodEXT \n "
" #define textureCubeLod textureCubeLodEXT \n "
) ;
}
else
{
writeString ( & writer
, " #define texture2DLod(_sampler, _coord, _level) texture2D(_sampler, _coord) \n "
" #define texture2DProjLod(_sampler, _coord, _level) texture2DProj(_sampler, _coord) \n "
" #define textureCubeLod(_sampler, _coord, _level) textureCube(_sampler, _coord) \n "
) ;
}
2014-02-16 16:08:44 -08:00
}
2014-07-29 21:29:38 -07:00
if ( usesFragmentOrdering )
{
if ( s_extension [ Extension : : INTEL_fragment_shader_ordering ] . m_supported )
{
writeString ( & writer , " #extension GL_INTEL_fragment_shader_ordering : enable \n " ) ;
}
else
{
writeString ( & writer , " #define beginFragmentShaderOrdering() \n " ) ;
}
}
2015-02-12 08:26:21 -08:00
writeStringf ( & writer , " precision %s float; \n "
, m_type = = GL_FRAGMENT_SHADER ? " mediump " : " highp "
) ;
2013-12-12 22:35:27 -08:00
2014-05-10 20:51:44 -07:00
bx : : write ( & writer , code , codeLen ) ;
bx : : write ( & writer , ' \0 ' ) ;
2013-12-13 23:06:28 -08:00
2014-05-10 20:51:44 -07:00
if ( insertFragDepth )
2013-12-13 23:06:28 -08:00
{
2014-05-10 20:51:44 -07:00
char * entry = strstr ( temp , " void main () " ) ;
if ( NULL ! = entry )
2013-12-13 23:06:28 -08:00
{
2014-05-10 20:51:44 -07:00
char * brace = strstr ( entry , " { " ) ;
if ( NULL ! = brace )
2013-12-13 23:06:28 -08:00
{
2014-05-10 20:51:44 -07:00
const char * end = bx : : strmb ( brace , ' { ' , ' } ' ) ;
if ( NULL ! = end )
{
strins ( brace + 1 , " \n float bgfx_FragDepth = 0.0; \n " ) ;
}
2013-12-13 23:06:28 -08:00
}
}
}
2014-03-09 21:20:34 -07:00
2014-05-10 20:51:44 -07:00
// Replace all instances of gl_FragDepth with bgfx_FragDepth.
for ( const char * fragDepth = bx : : findIdentifierMatch ( temp , " gl_FragDepth " ) ; NULL ! = fragDepth ; fragDepth = bx : : findIdentifierMatch ( fragDepth , " gl_FragDepth " ) )
{
char * insert = const_cast < char * > ( fragDepth ) ;
strins ( insert , " bg " ) ;
memcpy ( insert + 2 , " fx " , 2 ) ;
}
2014-03-09 21:20:34 -07:00
}
2014-05-10 20:51:44 -07:00
else if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
& & BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL < = 21 ) )
2014-02-09 16:46:50 -08:00
{
2015-03-16 21:44:33 -07:00
bool usesTextureLod = true
& & s_extension [ Extension : : ARB_shader_texture_lod ] . m_supported
2014-05-10 20:51:44 -07:00
& & bx : : findIdentifierMatch ( code , s_ARB_shader_texture_lod )
;
2014-04-19 18:16:26 -07:00
2015-03-17 14:18:27 +01:00
bool usesIUsamplers = ! ! bx : : findIdentifierMatch ( code , s_uisamplers ) ;
2015-03-16 21:44:33 -07:00
2015-05-30 15:58:45 -07:00
uint32_t version = usesIUsamplers
? 130
2015-05-30 10:07:07 -07:00
: ( usesTextureLod ? 120 : 0 )
;
2015-03-16 21:44:33 -07:00
if ( 0 ! = version )
2014-02-09 16:46:50 -08:00
{
2015-03-16 21:44:33 -07:00
writeStringf ( & writer , " #version %d \n " , version ) ;
}
2014-02-13 22:50:52 -08:00
2015-03-16 21:44:33 -07:00
if ( usesTextureLod )
{
2014-05-10 20:51:44 -07:00
if ( m_type = = GL_FRAGMENT_SHADER )
{
writeString ( & writer , " #extension GL_ARB_shader_texture_lod : enable \n " ) ;
}
}
2014-02-14 09:18:49 -08:00
2015-05-30 10:07:07 -07:00
if ( 130 < = version )
{
if ( m_type = = GL_FRAGMENT_SHADER )
{
writeString ( & writer , " #define varying in \n " ) ;
}
else
{
writeString ( & writer , " #define attribute in \n " ) ;
writeString ( & writer , " #define varying out \n " ) ;
}
uint32_t fragData = 0 ;
if ( ! ! bx : : findIdentifierMatch ( code , " gl_FragData " ) )
{
for ( uint32_t ii = 0 , num = g_caps . maxFBAttachments ; ii < num ; + + ii )
{
char tmpFragData [ 16 ] ;
bx : : snprintf ( tmpFragData , BX_COUNTOF ( tmpFragData ) , " gl_FragData[%d] " , ii ) ;
fragData = bx : : uint32_max ( fragData , NULL = = strstr ( code , tmpFragData ) ? 0 : ii + 1 ) ;
}
BGFX_FATAL ( 0 ! = fragData , Fatal : : InvalidShader , " Unable to find and patch gl_FragData! " ) ;
}
if ( 0 ! = fragData )
{
writeStringf ( & writer , " out vec4 bgfx_FragData[%d]; \n " , fragData ) ;
writeString ( & writer , " #define gl_FragData bgfx_FragData \n " ) ;
}
else
{
writeString ( & writer , " out vec4 bgfx_FragColor; \n " ) ;
writeString ( & writer , " #define gl_FragColor bgfx_FragColor \n " ) ;
}
}
2014-03-29 17:22:24 -07:00
writeString ( & writer
2014-05-10 20:51:44 -07:00
, " #define lowp \n "
" #define mediump \n "
" #define highp \n "
2014-06-25 18:43:26 -07:00
" #define flat \n "
" #define smooth \n "
" #define noperspective \n "
2014-05-10 20:51:44 -07:00
) ;
2014-03-29 17:22:24 -07:00
2014-05-10 20:51:44 -07:00
bx : : write ( & writer , code , codeLen ) ;
bx : : write ( & writer , ' \0 ' ) ;
}
else if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL > = 31 )
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
2014-02-09 16:46:50 -08:00
{
2014-05-10 20:51:44 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
2014-03-31 23:17:05 -07:00
{
2014-05-10 20:51:44 -07:00
writeString ( & writer
, " #version 300 es \n "
" precision mediump float; \n "
) ;
2014-03-31 23:17:05 -07:00
}
else
{
2014-05-10 20:51:44 -07:00
writeString ( & writer , " #version 140 \n " ) ;
2014-03-31 23:17:05 -07:00
}
2015-04-21 10:58:35 -07:00
writeString ( & writer , " #define texture2DLod textureLod \n " ) ;
writeString ( & writer , " #define texture3DLod textureLod \n " ) ;
writeString ( & writer , " #define textureCubeLod textureLod \n " ) ;
2014-05-10 20:51:44 -07:00
if ( m_type = = GL_FRAGMENT_SHADER )
{
writeString ( & writer , " #define varying in \n " ) ;
writeString ( & writer , " #define texture2D texture \n " ) ;
writeString ( & writer , " #define texture2DProj textureProj \n " ) ;
2014-04-01 22:31:02 -07:00
2014-05-10 20:51:44 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
{
writeString ( & writer , " #define shadow2D(_sampler, _coord) vec2(textureProj(_sampler, vec4(_coord, 1.0) ) ) \n " ) ;
writeString ( & writer , " #define shadow2DProj(_sampler, _coord) vec2(textureProj(_sampler, _coord) ) ) \n " ) ;
}
else
{
writeString ( & writer , " #define shadow2D(_sampler, _coord) (textureProj(_sampler, vec4(_coord, 1.0) ) ) \n " ) ;
writeString ( & writer , " #define shadow2DProj(_sampler, _coord) (textureProj(_sampler, _coord) ) ) \n " ) ;
}
2014-04-01 22:31:02 -07:00
2014-05-10 20:51:44 -07:00
writeString ( & writer , " #define texture3D texture \n " ) ;
writeString ( & writer , " #define textureCube texture \n " ) ;
2014-04-01 22:31:02 -07:00
2014-05-10 20:51:44 -07:00
uint32_t fragData = 0 ;
2014-04-01 22:31:02 -07:00
2014-05-10 20:51:44 -07:00
if ( ! ! bx : : findIdentifierMatch ( code , " gl_FragData " ) )
{
2014-09-01 11:24:51 -07:00
for ( uint32_t ii = 0 , num = g_caps . maxFBAttachments ; ii < num ; + + ii )
{
2015-03-29 22:40:35 -07:00
char tmpFragData [ 16 ] ;
bx : : snprintf ( tmpFragData , BX_COUNTOF ( tmpFragData ) , " gl_FragData[%d] " , ii ) ;
fragData = bx : : uint32_max ( fragData , NULL = = strstr ( code , tmpFragData ) ? 0 : ii + 1 ) ;
2014-09-01 11:24:51 -07:00
}
2014-05-10 20:51:44 -07:00
BGFX_FATAL ( 0 ! = fragData , Fatal : : InvalidShader , " Unable to find and patch gl_FragData! " ) ;
}
2014-07-29 21:29:38 -07:00
if ( ! ! bx : : findIdentifierMatch ( code , " beginFragmentShaderOrdering " ) )
{
if ( s_extension [ Extension : : INTEL_fragment_shader_ordering ] . m_supported )
{
writeString ( & writer , " #extension GL_INTEL_fragment_shader_ordering : enable \n " ) ;
}
else
{
writeString ( & writer , " #define beginFragmentShaderOrdering() \n " ) ;
}
}
2014-05-10 20:51:44 -07:00
if ( 0 ! = fragData )
{
writeStringf ( & writer , " out vec4 bgfx_FragData[%d]; \n " , fragData ) ;
writeString ( & writer , " #define gl_FragData bgfx_FragData \n " ) ;
}
else
{
writeString ( & writer , " out vec4 bgfx_FragColor; \n " ) ;
writeString ( & writer , " #define gl_FragColor bgfx_FragColor \n " ) ;
}
2014-04-01 22:31:02 -07:00
}
else
{
2014-05-10 20:51:44 -07:00
writeString ( & writer , " #define attribute in \n " ) ;
writeString ( & writer , " #define varying out \n " ) ;
2014-04-01 22:31:02 -07:00
}
2014-02-09 16:46:50 -08:00
2014-05-10 20:51:44 -07:00
if ( ! BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
{
writeString ( & writer
, " #define lowp \n "
" #define mediump \n "
" #define highp \n "
) ;
}
bx : : write ( & writer , code , codeLen ) ;
bx : : write ( & writer , ' \0 ' ) ;
2014-03-29 17:22:24 -07:00
}
2014-02-14 09:18:49 -08:00
2014-05-10 20:51:44 -07:00
code = temp ;
2014-02-09 16:46:50 -08:00
}
2013-12-12 22:35:27 -08:00
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 )
{
BX_TRACE ( " \n #### \n %s \n #### " , code ) ;
2014-02-26 20:24:35 -08:00
GLsizei len ;
2013-12-12 22:35:27 -08:00
char log [ 1024 ] ;
2014-02-26 20:24:35 -08:00
GL_CHECK ( glGetShaderInfoLog ( m_id , sizeof ( log ) , & len , log ) ) ;
2013-12-12 22:35:27 -08:00
BX_TRACE ( " Failed to compile shader. %d: %s " , compiled , log ) ;
GL_CHECK ( glDeleteShader ( m_id ) ) ;
2015-04-09 20:36:52 -07:00
m_id = 0 ;
2013-12-12 22:35:27 -08:00
BGFX_FATAL ( false , bgfx : : Fatal : : InvalidShader , " Failed to compile shader. " ) ;
}
2014-02-26 20:24:35 -08:00
else if ( BX_ENABLED ( BGFX_CONFIG_DEBUG )
2014-08-06 22:16:17 -07:00
& & s_extension [ Extension : : ANGLE_translated_shader_source ] . m_supported
& & NULL ! = glGetTranslatedShaderSourceANGLE )
2014-02-26 20:24:35 -08:00
{
GLsizei len ;
GL_CHECK ( glGetShaderiv ( m_id , GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE , & len ) ) ;
char * source = ( char * ) alloca ( len ) ;
GL_CHECK ( glGetTranslatedShaderSourceANGLE ( m_id , len , & len , source ) ) ;
BX_TRACE ( " ANGLE source (len: %d): \n %s \n #### " , len , source ) ;
}
2013-12-12 22:35:27 -08:00
}
}
2014-05-26 14:09:26 -07:00
void ShaderGL : : destroy ( )
2013-12-12 22:35:27 -08:00
{
if ( 0 ! = m_id )
{
GL_CHECK ( glDeleteShader ( m_id ) ) ;
m_id = 0 ;
}
}
2014-04-01 22:31:02 -07:00
static void frameBufferValidate ( )
{
GLenum complete = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
BX_CHECK ( GL_FRAMEBUFFER_COMPLETE = = complete
, " glCheckFramebufferStatus failed 0x%08x: %s "
, complete
, glEnumName ( complete )
) ;
BX_UNUSED ( complete ) ;
}
2016-02-15 16:55:32 -08:00
void FrameBufferGL : : create ( uint8_t _num , const Attachment * _attachment )
2012-07-08 19:10:07 -07:00
{
2014-02-05 23:07:11 -08:00
GL_CHECK ( glGenFramebuffers ( 1 , & m_fbo [ 0 ] ) ) ;
2015-04-14 17:02:41 -07:00
2015-04-13 22:13:16 -07:00
m_numTh = _num ;
2016-02-15 16:55:32 -08:00
memcpy ( m_attachment , _attachment , _num * sizeof ( Attachment ) ) ;
2015-04-14 17:02:41 -07:00
2015-04-13 22:13:16 -07:00
postReset ( ) ;
}
void FrameBufferGL : : postReset ( )
{
if ( 0 ! = m_fbo [ 0 ] )
{
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_fbo [ 0 ] ) ) ;
2013-02-17 20:42:33 -08:00
2015-04-13 22:13:16 -07:00
bool needResolve = false ;
2014-01-08 22:08:37 -08:00
2015-04-13 22:13:16 -07:00
GLenum buffers [ BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ] ;
2014-03-27 21:35:14 -07:00
2015-04-13 22:13:16 -07:00
uint32_t colorIdx = 0 ;
for ( uint32_t ii = 0 ; ii < m_numTh ; + + ii )
2012-07-08 19:10:07 -07:00
{
2016-02-15 16:55:32 -08:00
TextureHandle handle = m_attachment [ ii ] . handle ;
2015-04-13 22:13:16 -07:00
if ( isValid ( handle ) )
2014-02-24 22:10:19 -08:00
{
2015-04-13 22:13:16 -07:00
const TextureGL & texture = s_renderGL - > m_textures [ handle . idx ] ;
2014-02-24 22:10:19 -08:00
2015-04-13 22:13:16 -07:00
if ( 0 = = colorIdx )
2015-03-12 22:35:45 -07:00
{
2016-02-15 18:47:04 -08:00
m_width = bx : : uint32_max ( texture . m_width > > m_attachment [ ii ] . mip , 1 ) ;
m_height = bx : : uint32_max ( texture . m_height > > m_attachment [ ii ] . mip , 1 ) ;
2015-03-12 22:35:45 -07:00
}
2015-04-13 22:13:16 -07:00
GLenum attachment = GL_COLOR_ATTACHMENT0 + colorIdx ;
TextureFormat : : Enum format = ( TextureFormat : : Enum ) texture . m_textureFormat ;
if ( isDepth ( format ) )
2015-03-12 22:35:45 -07:00
{
2015-04-13 22:13:16 -07:00
const ImageBlockInfo & info = getBlockInfo ( format ) ;
if ( 0 < info . stencilBits )
{
attachment = GL_DEPTH_STENCIL_ATTACHMENT ;
}
else if ( 0 = = info . depthBits )
{
attachment = GL_STENCIL_ATTACHMENT ;
}
else
{
attachment = GL_DEPTH_ATTACHMENT ;
}
2015-03-12 22:35:45 -07:00
}
else
{
2015-04-13 22:13:16 -07:00
buffers [ colorIdx ] = attachment ;
+ + colorIdx ;
2015-03-12 22:35:45 -07:00
}
2015-04-13 22:13:16 -07:00
if ( 0 ! = texture . m_rbo )
{
GL_CHECK ( glFramebufferRenderbuffer ( GL_FRAMEBUFFER
, attachment
, GL_RENDERBUFFER
, texture . m_rbo
) ) ;
}
else
{
2015-10-19 15:09:56 -07:00
GLenum target = GL_TEXTURE_CUBE_MAP = = texture . m_target
2016-02-15 16:55:32 -08:00
? GL_TEXTURE_CUBE_MAP_POSITIVE_X + m_attachment [ ii ] . layer
2015-10-19 15:09:56 -07:00
: texture . m_target
;
2015-04-13 22:13:16 -07:00
GL_CHECK ( glFramebufferTexture2D ( GL_FRAMEBUFFER
, attachment
2015-10-19 15:09:56 -07:00
, target
2015-04-13 22:13:16 -07:00
, texture . m_id
2016-02-15 16:55:32 -08:00
, m_attachment [ ii ] . mip
2015-04-13 22:13:16 -07:00
) ) ;
}
needResolve | = ( 0 ! = texture . m_rbo ) & & ( 0 ! = texture . m_id ) ;
2013-02-18 21:17:29 -08:00
}
2015-04-13 22:13:16 -07:00
}
m_num = uint8_t ( colorIdx ) ;
2012-07-08 19:10:07 -07:00
2015-08-26 18:02:05 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 31 ) )
2015-04-13 22:13:16 -07:00
{
if ( 0 = = colorIdx )
2013-12-29 11:43:44 -08:00
{
2015-08-26 18:02:05 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
{
// When only depth is attached disable draw buffer to avoid
// GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER.
GL_CHECK ( glDrawBuffer ( GL_NONE ) ) ;
}
2013-12-29 11:43:44 -08:00
}
2014-02-05 23:07:11 -08:00
else
2013-12-29 11:43:44 -08:00
{
2015-04-13 22:13:16 -07:00
GL_CHECK ( glDrawBuffers ( colorIdx , buffers ) ) ;
2013-12-29 11:43:44 -08:00
}
2015-01-08 20:43:36 -08:00
2015-04-13 22:13:16 -07:00
// Disable read buffer to avoid GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER.
GL_CHECK ( glReadBuffer ( GL_NONE ) ) ;
2012-07-08 19:10:07 -07:00
}
2014-02-05 23:07:11 -08:00
2015-04-13 22:13:16 -07:00
frameBufferValidate ( ) ;
2014-03-25 23:07:51 -07:00
2015-04-13 22:13:16 -07:00
if ( needResolve )
2014-03-27 21:35:14 -07:00
{
2015-04-13 22:13:16 -07:00
GL_CHECK ( glGenFramebuffers ( 1 , & m_fbo [ 1 ] ) ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_fbo [ 1 ] ) ) ;
2014-02-24 22:00:26 -08:00
2015-04-13 22:13:16 -07:00
colorIdx = 0 ;
for ( uint32_t ii = 0 ; ii < m_numTh ; + + ii )
2014-02-05 23:07:11 -08:00
{
2016-02-15 16:55:32 -08:00
TextureHandle handle = m_attachment [ ii ] . handle ;
2015-04-13 22:13:16 -07:00
if ( isValid ( handle ) )
2014-02-05 23:07:11 -08:00
{
2015-04-13 22:13:16 -07:00
const TextureGL & texture = s_renderGL - > m_textures [ handle . idx ] ;
if ( 0 ! = texture . m_id )
2014-02-05 23:07:11 -08:00
{
2015-04-13 22:13:16 -07:00
GLenum attachment = GL_COLOR_ATTACHMENT0 + colorIdx ;
if ( ! isDepth ( ( TextureFormat : : Enum ) texture . m_textureFormat ) )
{
+ + colorIdx ;
2016-02-15 16:55:32 -08:00
GLenum target = GL_TEXTURE_CUBE_MAP = = texture . m_target
? GL_TEXTURE_CUBE_MAP_POSITIVE_X + m_attachment [ ii ] . layer
: texture . m_target
;
2015-04-13 22:13:16 -07:00
GL_CHECK ( glFramebufferTexture2D ( GL_FRAMEBUFFER
, attachment
2016-02-15 16:55:32 -08:00
, target
2015-04-13 22:13:16 -07:00
, texture . m_id
2016-02-15 16:55:32 -08:00
, m_attachment [ ii ] . mip
2015-04-13 22:13:16 -07:00
) ) ;
}
2014-02-05 23:07:11 -08:00
}
}
}
2015-04-13 22:13:16 -07:00
frameBufferValidate ( ) ;
2012-07-08 19:10:07 -07:00
}
2015-04-13 22:13:16 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , s_renderGL - > m_msaaBackBufferFbo ) ) ;
2013-02-18 21:17:29 -08:00
}
2012-07-08 19:10:07 -07:00
}
2014-09-07 17:17:38 -07:00
void FrameBufferGL : : create ( uint16_t _denseIdx , void * _nwh , uint32_t _width , uint32_t _height , TextureFormat : : Enum _depthFormat )
{
BX_UNUSED ( _depthFormat ) ;
m_swapChain = s_renderGL - > m_glctx . createSwapChain ( _nwh ) ;
m_width = _width ;
m_height = _height ;
m_denseIdx = _denseIdx ;
}
uint16_t FrameBufferGL : : destroy ( )
2012-07-08 19:10:07 -07:00
{
2014-09-23 20:35:39 -07:00
if ( 0 ! = m_num )
{
GL_CHECK ( glDeleteFramebuffers ( 0 = = m_fbo [ 1 ] ? 1 : 2 , m_fbo ) ) ;
m_num = 0 ;
}
2014-09-07 17:17:38 -07:00
if ( NULL ! = m_swapChain )
{
2014-11-30 09:06:47 -08:00
s_renderGL - > m_glctx . destroySwapChain ( m_swapChain ) ;
2014-09-07 17:17:38 -07:00
m_swapChain = NULL ;
}
2015-04-14 17:02:04 -07:00
memset ( m_fbo , 0 , sizeof ( m_fbo ) ) ;
2014-09-07 17:17:38 -07:00
uint16_t denseIdx = m_denseIdx ;
m_denseIdx = UINT16_MAX ;
2015-01-08 20:43:36 -08:00
2014-09-07 17:17:38 -07:00
return denseIdx ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
void FrameBufferGL : : resolve ( )
2013-02-17 20:42:33 -08:00
{
2014-02-05 23:07:11 -08:00
if ( 0 ! = m_fbo [ 1 ] )
{
GL_CHECK ( glBindFramebuffer ( GL_READ_FRAMEBUFFER , m_fbo [ 0 ] ) ) ;
2014-02-25 22:20:09 -08:00
GL_CHECK ( glReadBuffer ( GL_COLOR_ATTACHMENT0 ) ) ;
2014-02-05 23:07:11 -08:00
GL_CHECK ( glBindFramebuffer ( GL_DRAW_FRAMEBUFFER , m_fbo [ 1 ] ) ) ;
GL_CHECK ( glBlitFramebuffer ( 0
2013-02-17 20:42:33 -08:00
, 0
, m_width
, m_height
, 0
, 0
, m_width
, m_height
, GL_COLOR_BUFFER_BIT
, GL_LINEAR
) ) ;
2014-02-25 22:20:09 -08:00
GL_CHECK ( glBindFramebuffer ( GL_READ_FRAMEBUFFER , m_fbo [ 0 ] ) ) ;
GL_CHECK ( glReadBuffer ( GL_NONE ) ) ;
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , s_renderGL - > m_msaaBackBufferFbo ) ) ;
2014-04-15 19:10:56 -07:00
}
2013-06-10 22:41:03 -07:00
}
2015-04-07 17:58:14 -07:00
void FrameBufferGL : : discard ( uint16_t _flags )
2015-01-11 18:00:08 -08:00
{
GLenum buffers [ BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + 2 ] ;
uint32_t idx = 0 ;
if ( BGFX_CLEAR_NONE ! = ( _flags & BGFX_CLEAR_DISCARD_COLOR_MASK ) )
{
for ( uint32_t ii = 0 , num = m_num ; ii < num ; + + ii )
{
if ( BGFX_CLEAR_NONE ! = ( _flags & ( BGFX_CLEAR_DISCARD_COLOR_0 < < ii ) ) )
{
buffers [ idx + + ] = GL_COLOR_ATTACHMENT0 + ii ;
}
}
}
uint32_t dsFlags = _flags & ( BGFX_CLEAR_DISCARD_DEPTH | BGFX_CLEAR_DISCARD_STENCIL ) ;
if ( BGFX_CLEAR_NONE ! = dsFlags )
{
if ( ( BGFX_CLEAR_DISCARD_DEPTH | BGFX_CLEAR_DISCARD_STENCIL ) = = dsFlags )
{
buffers [ idx + + ] = GL_DEPTH_STENCIL_ATTACHMENT ;
}
else if ( BGFX_CLEAR_DISCARD_DEPTH = = dsFlags )
{
buffers [ idx + + ] = GL_DEPTH_ATTACHMENT ;
}
else if ( BGFX_CLEAR_DISCARD_STENCIL = = dsFlags )
{
buffers [ idx + + ] = GL_STENCIL_ATTACHMENT ;
}
}
GL_CHECK ( glInvalidateFramebuffer ( GL_FRAMEBUFFER , idx , buffers ) ) ;
}
2015-11-01 19:12:42 -08:00
void OcclusionQueryGL : : create ( )
{
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_query ) ; + + ii )
{
Query & query = m_query [ ii ] ;
GL_CHECK ( glGenQueries ( 1 , & query . m_id ) ) ;
}
}
void OcclusionQueryGL : : destroy ( )
{
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( m_query ) ; + + ii )
{
Query & query = m_query [ ii ] ;
GL_CHECK ( glDeleteQueries ( 1 , & query . m_id ) ) ;
}
}
2015-11-03 16:00:14 -08:00
void OcclusionQueryGL : : begin ( Frame * _render , OcclusionQueryHandle _handle )
2015-11-01 19:12:42 -08:00
{
while ( 0 = = m_control . reserve ( 1 ) )
{
2015-11-03 16:00:14 -08:00
resolve ( _render , true ) ;
2015-11-01 19:12:42 -08:00
}
Query & query = m_query [ m_control . m_current ] ;
GL_CHECK ( glBeginQuery ( GL_SAMPLES_PASSED , query . m_id ) ) ;
query . m_handle = _handle ;
}
void OcclusionQueryGL : : end ( )
{
GL_CHECK ( glEndQuery ( GL_SAMPLES_PASSED ) ) ;
m_control . commit ( 1 ) ;
}
2015-11-03 16:00:14 -08:00
void OcclusionQueryGL : : resolve ( Frame * _render , bool _wait )
2015-11-01 19:12:42 -08:00
{
while ( 0 ! = m_control . available ( ) )
{
Query & query = m_query [ m_control . m_read ] ;
int32_t result ;
if ( ! _wait )
{
GL_CHECK ( glGetQueryObjectiv ( query . m_id , GL_QUERY_RESULT_AVAILABLE , & result ) ) ;
if ( ! result )
{
break ;
}
}
GL_CHECK ( glGetQueryObjectiv ( query . m_id , GL_QUERY_RESULT , & result ) ) ;
2015-11-03 16:00:14 -08:00
_render - > m_occlusion [ query . m_handle . idx ] = 0 < result ;
2015-11-01 19:12:42 -08:00
m_control . consume ( 1 ) ;
}
}
2014-05-26 14:09:26 -07:00
void RendererContextGL : : submit ( Frame * _render , ClearQuad & _clearQuad , TextVideoMemBlitter & _textVideoMemBlitter )
2012-07-08 19:10:07 -07:00
{
2015-11-16 10:42:56 -04:00
BGFX_GPU_PROFILER_BEGIN_DYNAMIC ( " rendererSubmit " ) ;
2014-09-24 19:22:15 -07:00
if ( 1 < m_numWindows
& & m_vaoSupport )
{
m_vaoSupport = false ;
GL_CHECK ( glBindVertexArray ( 0 ) ) ;
GL_CHECK ( glDeleteVertexArrays ( 1 , & m_vao ) ) ;
m_vao = 0 ;
m_vaoStateCache . invalidate ( ) ;
}
2014-09-07 17:17:38 -07:00
m_glctx . makeCurrent ( NULL ) ;
2014-09-24 19:22:15 -07:00
const GLuint defaultVao = m_vao ;
2013-03-03 22:30:50 -08:00
if ( 0 ! = defaultVao )
2013-01-21 23:36:47 -08:00
{
2013-03-03 22:30:50 -08:00
GL_CHECK ( glBindVertexArray ( defaultVao ) ) ;
2013-01-21 23:36:47 -08:00
}
2014-09-24 19:22:15 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_backBufferFbo ) ) ;
2013-01-21 23:36:47 -08:00
2014-05-26 14:09:26 -07:00
updateResolution ( _render - > m_resolution ) ;
2012-07-08 19:10:07 -07:00
int64_t elapsed = - bx : : getHPCounter ( ) ;
2013-01-01 13:19:10 -08:00
int64_t captureElapsed = 0 ;
2015-07-22 18:05:11 -07:00
if ( m_timerQuerySupport )
2012-07-08 19:10:07 -07:00
{
2015-08-16 15:37:46 -07:00
m_gpuTimer . begin ( ) ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
if ( 0 < _render - > m_iboffset )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
TransientIndexBuffer * ib = _render - > m_transientIb ;
2016-03-13 18:13:10 -07:00
m_indexBuffers [ ib - > handle . idx ] . update ( 0 , _render - > m_iboffset , ib - > data , true ) ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
if ( 0 < _render - > m_vboffset )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
TransientVertexBuffer * vb = _render - > m_transientVb ;
2016-03-13 18:13:10 -07:00
m_vertexBuffers [ vb - > handle . idx ] . update ( 0 , _render - > m_vboffset , vb - > data , true ) ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
_render - > sort ( ) ;
2012-07-08 19:10:07 -07:00
2014-07-20 20:27:13 -07:00
RenderDraw currentState ;
currentState . clear ( ) ;
2015-11-01 17:28:23 -08:00
currentState . m_stateFlags = BGFX_STATE_NONE ;
currentState . m_stencil = packStencil ( BGFX_STENCIL_NONE , BGFX_STENCIL_NONE ) ;
2012-07-08 19:10:07 -07:00
2015-06-02 17:00:36 -07:00
_render - > m_hmdInitialized = m_ovr . isInitialized ( ) ;
2014-10-28 22:08:55 -07:00
2015-06-02 17:00:36 -07:00
const bool hmdEnabled = m_ovr . isEnabled ( ) | | m_ovr . isDebug ( ) ;
2014-12-27 19:00:41 -08:00
ViewState viewState ( _render , hmdEnabled ) ;
2014-05-10 20:51:44 -07:00
2012-09-16 17:36:08 -07:00
uint16_t programIdx = invalidHandle ;
2012-07-08 19:10:07 -07:00
SortKey key ;
2015-08-28 20:34:14 -07:00
uint16_t view = UINT16_MAX ;
2015-12-30 17:46:05 -08:00
FrameBufferHandle fbh = { BGFX_CONFIG_MAX_FRAME_BUFFERS } ;
2015-10-15 16:38:59 -07:00
BlitKey blitKey ;
blitKey . decode ( _render - > m_blitKeys [ 0 ] ) ;
uint16_t numBlitItems = _render - > m_numBlitItems ;
uint16_t blitItem = 0 ;
2015-10-15 20:58:31 -07:00
int32_t resolutionHeight = hmdEnabled
2014-10-28 22:08:55 -07:00
? _render - > m_hmd . height
: _render - > m_resolution . m_height
;
2013-03-29 22:58:50 -07:00
uint32_t blendFactor = 0 ;
2014-04-26 23:48:41 -07:00
2015-03-29 22:40:35 -07:00
uint8_t primIndex ;
{
const uint64_t pt = _render - > m_debug & BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : 0 ;
primIndex = uint8_t ( pt > > BGFX_STATE_PT_SHIFT ) ;
}
2014-04-26 23:48:41 -07:00
PrimInfo prim = s_primInfo [ primIndex ] ;
2012-07-08 19:10:07 -07:00
uint32_t baseVertex = 0 ;
2013-01-21 23:36:47 -08:00
GLuint currentVao = 0 ;
2015-04-02 11:57:53 -07:00
bool wasCompute = false ;
2013-08-01 22:55:26 -07:00
bool viewHasScissor = false ;
Rect viewScissorRect ;
2013-08-04 16:56:07 -07:00
viewScissorRect . clear ( ) ;
2015-04-07 17:58:14 -07:00
uint16_t discardFlags = BGFX_CLEAR_NONE ;
2012-07-08 19:10:07 -07:00
2014-03-26 23:37:01 -07:00
const bool blendIndependentSupported = s_extension [ Extension : : ARB_draw_buffers_blend ] . m_supported ;
2014-07-20 20:27:13 -07:00
const bool computeSupported = ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) & & s_extension [ Extension : : ARB_compute_shader ] . m_supported )
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 )
;
2014-03-26 23:37:01 -07:00
2014-04-26 23:48:41 -07:00
uint32_t statsNumPrimsSubmitted [ BX_COUNTOF ( s_primInfo ) ] = { } ;
uint32_t statsNumPrimsRendered [ BX_COUNTOF ( s_primInfo ) ] = { } ;
uint32_t statsNumInstances [ BX_COUNTOF ( s_primInfo ) ] = { } ;
2012-07-08 19:10:07 -07:00
uint32_t statsNumIndices = 0 ;
2015-03-26 22:43:50 -07:00
uint32_t statsKeyType [ 2 ] = { } ;
2012-07-08 19:10:07 -07:00
2015-11-01 19:12:42 -08:00
if ( m_occlusionQuerySupport )
{
2015-11-03 16:00:14 -08:00
m_occlusionQuery . resolve ( _render ) ;
2015-11-01 19:12:42 -08:00
}
2014-05-26 14:09:26 -07:00
if ( 0 = = ( _render - > m_debug & BGFX_DEBUG_IFH ) )
2012-07-08 19:10:07 -07:00
{
2014-09-24 19:22:15 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_msaaBackBufferFbo ) ) ;
2013-02-21 22:05:33 -08:00
2014-10-28 22:08:55 -07:00
bool viewRestart = false ;
uint8_t eye = 0 ;
uint8_t restartState = 0 ;
2014-12-27 19:00:41 -08:00
viewState . m_rect = _render - > m_rect [ 0 ] ;
2014-10-28 22:08:55 -07:00
int32_t numItems = _render - > m_num ;
for ( int32_t item = 0 , restartItem = numItems ; item < numItems | | restartItem < numItems ; )
2012-07-08 19:10:07 -07:00
{
2015-02-21 15:40:51 -08:00
const bool isCompute = key . decode ( _render - > m_sortKeys [ item ] , _render - > m_viewRemap ) ;
2015-03-26 22:43:50 -07:00
statsKeyType [ isCompute ] + + ;
2014-10-28 22:08:55 -07:00
const bool viewChanged = 0
| | key . m_view ! = view
| | item = = numItems
;
2012-07-08 19:10:07 -07:00
2014-07-20 20:27:13 -07:00
const RenderItem & renderItem = _render - > m_renderItem [ _render - > m_sortValues [ item ] ] ;
2014-10-28 22:08:55 -07:00
+ + item ;
2012-07-08 19:10:07 -07:00
2014-07-20 20:27:13 -07:00
if ( viewChanged )
2012-07-08 19:10:07 -07:00
{
2014-10-28 22:08:55 -07:00
if ( 1 = = restartState )
{
restartState = 2 ;
item = restartItem ;
restartItem = numItems ;
2015-08-28 20:34:14 -07:00
view = UINT16_MAX ;
2014-10-28 22:08:55 -07:00
continue ;
}
2012-07-08 19:10:07 -07:00
view = key . m_view ;
2012-09-16 17:36:08 -07:00
programIdx = invalidHandle ;
2012-07-08 19:10:07 -07:00
2014-05-26 14:09:26 -07:00
if ( _render - > m_fb [ view ] . idx ! = fbh . idx )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
fbh = _render - > m_fb [ view ] ;
2015-10-15 20:58:31 -07:00
resolutionHeight = hmdEnabled
2014-10-28 22:08:55 -07:00
? _render - > m_hmd . height
: _render - > m_resolution . m_height
;
2015-10-15 20:58:31 -07:00
resolutionHeight = setFrameBuffer ( fbh , resolutionHeight , discardFlags ) ;
2014-10-28 22:08:55 -07:00
}
viewRestart = ( ( BGFX_VIEW_STEREO = = ( _render - > m_viewFlags [ view ] & BGFX_VIEW_STEREO ) ) ) ;
viewRestart & = hmdEnabled ;
if ( viewRestart )
{
if ( 0 = = restartState )
{
restartState = 1 ;
restartItem = item - 1 ;
}
eye = ( restartState - 1 ) & 1 ;
restartState & = 1 ;
}
else
{
eye = 0 ;
}
2015-11-16 10:42:56 -04:00
if ( item > 1 )
{
BGFX_GPU_PROFILER_END ( ) ;
BGFX_PROFILER_END ( ) ;
}
BGFX_PROFILER_BEGIN_DYNAMIC ( s_viewName [ view ] ) ;
BGFX_GPU_PROFILER_BEGIN_DYNAMIC ( s_viewName [ view ] ) ;
2014-12-27 19:00:41 -08:00
viewState . m_rect = _render - > m_rect [ view ] ;
2014-10-28 22:08:55 -07:00
if ( viewRestart )
{
2015-04-02 11:57:53 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG_PIX ) )
{
char * viewName = s_viewName [ view ] ;
viewName [ 3 ] = ' ' ;
viewName [ 4 ] = eye ? ' R ' : ' L ' ;
GL_CHECK ( glInsertEventMarker ( 0 , viewName ) ) ;
}
2015-01-08 20:43:36 -08:00
2015-06-05 10:43:43 -07:00
if ( m_ovr . isEnabled ( ) )
2015-06-05 02:00:26 -07:00
{
m_ovr . getViewport ( eye , & viewState . m_rect ) ;
}
else
{
viewState . m_rect . m_x = eye * ( viewState . m_rect . m_width + 1 ) / 2 ;
viewState . m_rect . m_width / = 2 ;
}
2014-10-28 22:08:55 -07:00
}
else
{
2015-04-02 11:57:53 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG_PIX ) )
{
char * viewName = s_viewName [ view ] ;
viewName [ 3 ] = ' ' ;
viewName [ 4 ] = ' ' ;
GL_CHECK ( glInsertEventMarker ( 0 , viewName ) ) ;
}
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
const Rect & scissorRect = _render - > m_scissor [ view ] ;
2013-08-01 22:55:26 -07:00
viewHasScissor = ! scissorRect . isZero ( ) ;
2014-12-27 19:00:41 -08:00
viewScissorRect = viewHasScissor ? scissorRect : viewState . m_rect ;
2012-07-08 19:10:07 -07:00
2014-12-27 19:00:41 -08:00
GL_CHECK ( glViewport ( viewState . m_rect . m_x
2015-10-15 20:58:31 -07:00
, resolutionHeight - viewState . m_rect . m_height - viewState . m_rect . m_y
2014-12-27 19:00:41 -08:00
, viewState . m_rect . m_width
, viewState . m_rect . m_height
2014-10-28 22:08:55 -07:00
) ) ;
2012-07-08 19:10:07 -07:00
2014-05-26 14:09:26 -07:00
Clear & clear = _render - > m_clear [ view ] ;
2015-01-11 18:00:08 -08:00
discardFlags = clear . m_flags & BGFX_CLEAR_DISCARD_MASK ;
2012-07-08 19:10:07 -07:00
2015-01-11 18:00:08 -08:00
if ( BGFX_CLEAR_NONE ! = ( clear . m_flags & BGFX_CLEAR_MASK ) )
2012-07-08 19:10:07 -07:00
{
2015-10-15 20:58:31 -07:00
clearQuad ( _clearQuad , viewState . m_rect , clear , resolutionHeight , _render - > m_colorPalette ) ;
2012-07-08 19:10:07 -07:00
}
2012-12-26 22:52:10 -08:00
GL_CHECK ( glDisable ( GL_STENCIL_TEST ) ) ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glEnable ( GL_DEPTH_TEST ) ) ;
GL_CHECK ( glDepthFunc ( GL_LESS ) ) ;
GL_CHECK ( glEnable ( GL_CULL_FACE ) ) ;
GL_CHECK ( glDisable ( GL_BLEND ) ) ;
2015-10-15 16:38:59 -07:00
2015-10-16 17:42:40 -07:00
if ( m_blitSupported )
2015-10-15 16:38:59 -07:00
{
2015-10-16 17:42:40 -07:00
for ( ; blitItem < numBlitItems & & blitKey . m_view < = view ; blitItem + + )
{
const BlitItem & bi = _render - > m_blitItem [ blitItem ] ;
blitKey . decode ( _render - > m_blitKeys [ blitItem + 1 ] ) ;
const TextureGL & src = m_textures [ bi . m_src . idx ] ;
const TextureGL & dst = m_textures [ bi . m_dst . idx ] ;
uint32_t srcWidth = bx : : uint32_min ( src . m_width , bi . m_srcX + bi . m_width ) - bi . m_srcX ;
uint32_t srcHeight = bx : : uint32_min ( src . m_height , bi . m_srcY + bi . m_height ) - bi . m_srcY ;
uint32_t srcDepth = bx : : uint32_min ( src . m_depth , bi . m_srcZ + bi . m_depth ) - bi . m_srcZ ;
uint32_t dstWidth = bx : : uint32_min ( dst . m_width , bi . m_dstX + bi . m_width ) - bi . m_dstX ;
uint32_t dstHeight = bx : : uint32_min ( dst . m_height , bi . m_dstY + bi . m_height ) - bi . m_dstY ;
uint32_t dstDepth = bx : : uint32_min ( dst . m_depth , bi . m_dstZ + bi . m_depth ) - bi . m_dstZ ;
uint32_t width = bx : : uint32_min ( srcWidth , dstWidth ) ;
uint32_t height = bx : : uint32_min ( srcHeight , dstHeight ) ;
uint32_t depth = bx : : uint32_min ( srcDepth , dstDepth ) ;
GL_CHECK ( glCopyImageSubData ( src . m_id
, src . m_target
, bi . m_srcMip
, bi . m_srcX
, bi . m_srcY
, bi . m_srcZ
, dst . m_id
, dst . m_target
, bi . m_dstMip
, bi . m_dstX
, bi . m_dstY
, bi . m_dstZ
, width
, height
2015-10-17 17:39:44 -07:00
, bx : : uint32_imax ( depth , 1 )
2015-10-16 17:42:40 -07:00
) ) ;
}
2015-10-15 16:38:59 -07:00
}
2012-07-08 19:10:07 -07:00
}
2014-07-20 20:27:13 -07:00
if ( isCompute )
{
2015-04-02 11:57:53 -07:00
if ( ! wasCompute )
{
wasCompute = true ;
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG_PIX ) )
{
char * viewName = s_viewName [ view ] ;
viewName [ 3 ] = ' C ' ;
GL_CHECK ( glInsertEventMarker ( 0 , viewName ) ) ;
}
}
2014-07-20 20:27:13 -07:00
if ( computeSupported )
{
const RenderCompute & compute = renderItem . compute ;
ProgramGL & program = m_program [ key . m_program ] ;
GL_CHECK ( glUseProgram ( program . m_id ) ) ;
GLbitfield barrier = 0 ;
for ( uint32_t ii = 0 ; ii < BGFX_MAX_COMPUTE_BINDINGS ; + + ii )
{
2015-01-13 22:34:48 -08:00
const Binding & bind = compute . m_bind [ ii ] ;
2014-07-20 20:27:13 -07:00
if ( invalidHandle ! = bind . m_idx )
{
switch ( bind . m_type )
{
2015-01-13 22:34:48 -08:00
case Binding : : Image :
2014-07-20 20:27:13 -07:00
{
const TextureGL & texture = m_textures [ bind . m_idx ] ;
2015-01-13 22:34:48 -08:00
GL_CHECK ( glBindImageTexture ( ii
, texture . m_id
, bind . m_un . m_compute . m_mip
, GL_FALSE
, 0
, s_access [ bind . m_un . m_compute . m_access ]
, s_imageFormat [ bind . m_un . m_compute . m_format ] )
) ;
2014-07-20 20:27:13 -07:00
barrier | = GL_SHADER_IMAGE_ACCESS_BARRIER_BIT ;
}
break ;
2015-01-13 22:34:48 -08:00
case Binding : : IndexBuffer :
2014-07-20 20:27:13 -07:00
{
2015-01-10 20:38:47 -08:00
const IndexBufferGL & buffer = m_indexBuffers [ bind . m_idx ] ;
2015-07-16 20:28:43 -07:00
GL_CHECK ( glBindBufferBase ( GL_SHADER_STORAGE_BUFFER , ii , buffer . m_id ) ) ;
2015-01-10 20:38:47 -08:00
barrier | = GL_SHADER_STORAGE_BARRIER_BIT ;
}
break ;
2015-01-13 22:34:48 -08:00
case Binding : : VertexBuffer :
2015-01-10 20:38:47 -08:00
{
const VertexBufferGL & buffer = m_vertexBuffers [ bind . m_idx ] ;
2015-07-16 20:28:43 -07:00
GL_CHECK ( glBindBufferBase ( GL_SHADER_STORAGE_BUFFER , ii , buffer . m_id ) ) ;
2014-12-09 23:16:27 -08:00
barrier | = GL_SHADER_STORAGE_BARRIER_BIT ;
2014-07-20 20:27:13 -07:00
}
break ;
}
}
}
if ( 0 ! = barrier )
{
bool constantsChanged = compute . m_constBegin < compute . m_constEnd ;
2015-09-14 15:53:33 -07:00
rendererUpdateUniforms ( this , _render - > m_uniformBuffer , compute . m_constBegin , compute . m_constEnd ) ;
2014-07-20 20:27:13 -07:00
2014-10-08 19:58:29 -07:00
if ( constantsChanged
& & NULL ! = program . m_constantBuffer )
2014-07-20 20:27:13 -07:00
{
commit ( * program . m_constantBuffer ) ;
}
2014-12-27 19:00:41 -08:00
viewState . setPredefined < 1 > ( this , view , eye , program , _render , compute ) ;
2015-05-01 14:54:23 -07:00
if ( isValid ( compute . m_indirectBuffer ) )
{
const VertexBufferGL & vb = m_vertexBuffers [ compute . m_indirectBuffer . idx ] ;
if ( currentState . m_indirectBuffer . idx ! = compute . m_indirectBuffer . idx )
{
currentState . m_indirectBuffer = compute . m_indirectBuffer ;
GL_CHECK ( glBindBuffer ( GL_DISPATCH_INDIRECT_BUFFER , vb . m_id ) ) ;
}
uint32_t numDrawIndirect = UINT16_MAX = = compute . m_numIndirect
? vb . m_size / BGFX_CONFIG_DRAW_INDIRECT_STRIDE
: compute . m_numIndirect
;
uintptr_t args = compute . m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE ;
for ( uint32_t ii = 0 ; ii < numDrawIndirect ; + + ii )
{
2015-08-28 11:17:26 -07:00
GL_CHECK ( glDispatchComputeIndirect ( ( GLintptr ) args ) ) ;
2015-05-01 14:54:23 -07:00
args + = BGFX_CONFIG_DRAW_INDIRECT_STRIDE ;
}
}
else
{
if ( isValid ( currentState . m_indirectBuffer ) )
{
currentState . m_indirectBuffer . idx = invalidHandle ;
GL_CHECK ( glBindBuffer ( GL_DISPATCH_INDIRECT_BUFFER , 0 ) ) ;
}
GL_CHECK ( glDispatchCompute ( compute . m_numX , compute . m_numY , compute . m_numZ ) ) ;
}
2014-07-20 20:27:13 -07:00
GL_CHECK ( glMemoryBarrier ( barrier ) ) ;
}
}
continue ;
}
2015-04-16 11:38:46 -07:00
bool resetState = viewChanged | | wasCompute ;
2015-04-02 11:57:53 -07:00
if ( wasCompute )
{
wasCompute = false ;
if ( BX_ENABLED ( BGFX_CONFIG_DEBUG_PIX ) )
{
char * viewName = s_viewName [ view ] ;
viewName [ 3 ] = ' ' ;
GL_CHECK ( glInsertEventMarker ( 0 , viewName ) ) ;
}
}
2014-07-20 20:27:13 -07:00
const RenderDraw & draw = renderItem . draw ;
2015-11-01 19:12:42 -08:00
const bool hasOcclusionQuery = 0 ! = ( draw . m_stateFlags & BGFX_STATE_INTERNAL_OCCLUSION_QUERY ) ;
if ( isValid ( draw . m_occlusionQuery )
& & ! hasOcclusionQuery
2015-11-03 16:00:14 -08:00
& & ! isVisible ( _render , draw . m_occlusionQuery , 0 ! = ( draw . m_submitFlags & BGFX_SUBMIT_INTERNAL_OCCLUSION_VISIBLE ) ) )
2015-11-01 19:12:42 -08:00
{
continue ;
}
2015-11-01 17:28:23 -08:00
const uint64_t newFlags = draw . m_stateFlags ;
uint64_t changedFlags = currentState . m_stateFlags ^ draw . m_stateFlags ;
currentState . m_stateFlags = newFlags ;
2014-07-20 20:27:13 -07:00
const uint64_t newStencil = draw . m_stencil ;
uint64_t changedStencil = currentState . m_stencil ^ draw . m_stencil ;
currentState . m_stencil = newStencil ;
2015-04-16 11:38:46 -07:00
if ( resetState )
2014-07-20 20:27:13 -07:00
{
currentState . clear ( ) ;
currentState . m_scissor = ! draw . m_scissor ;
changedFlags = BGFX_STATE_MASK ;
changedStencil = packStencil ( BGFX_STENCIL_MASK , BGFX_STENCIL_MASK ) ;
2015-11-01 17:28:23 -08:00
currentState . m_stateFlags = newFlags ;
currentState . m_stencil = newStencil ;
2014-07-20 20:27:13 -07:00
}
uint16_t scissor = draw . m_scissor ;
2013-07-27 15:27:54 -07:00
if ( currentState . m_scissor ! = scissor )
{
currentState . m_scissor = scissor ;
if ( UINT16_MAX = = scissor )
{
2013-08-01 22:55:26 -07:00
if ( viewHasScissor )
2013-07-27 15:27:54 -07:00
{
GL_CHECK ( glEnable ( GL_SCISSOR_TEST ) ) ;
2014-10-28 21:41:34 -07:00
GL_CHECK ( glScissor ( viewScissorRect . m_x
2015-10-15 20:58:31 -07:00
, resolutionHeight - viewScissorRect . m_height - viewScissorRect . m_y
2014-10-28 21:41:34 -07:00
, viewScissorRect . m_width
, viewScissorRect . m_height
) ) ;
2013-07-27 15:27:54 -07:00
}
else
{
GL_CHECK ( glDisable ( GL_SCISSOR_TEST ) ) ;
}
}
else
{
2013-08-01 22:55:26 -07:00
Rect scissorRect ;
2014-05-26 14:09:26 -07:00
scissorRect . intersect ( viewScissorRect , _render - > m_rectCache . m_cache [ scissor ] ) ;
2013-07-27 15:27:54 -07:00
GL_CHECK ( glEnable ( GL_SCISSOR_TEST ) ) ;
2014-10-28 21:41:34 -07:00
GL_CHECK ( glScissor ( scissorRect . m_x
2015-10-15 20:58:31 -07:00
, resolutionHeight - scissorRect . m_height - scissorRect . m_y
2014-10-28 21:41:34 -07:00
, scissorRect . m_width
, scissorRect . m_height
) ) ;
2013-07-27 15:27:54 -07:00
}
}
2012-11-10 19:59:23 -08:00
if ( 0 ! = changedStencil )
{
if ( 0 ! = newStencil )
{
2012-12-26 22:52:10 -08:00
GL_CHECK ( glEnable ( GL_STENCIL_TEST ) ) ;
uint32_t bstencil = unpackStencil ( 1 , newStencil ) ;
2015-04-07 17:58:14 -07:00
uint8_t frontAndBack = bstencil ! = BGFX_STENCIL_NONE & & bstencil ! = unpackStencil ( 0 , newStencil ) ;
2012-12-26 22:52:10 -08:00
2012-11-10 19:59:23 -08:00
// uint32_t bchanged = unpackStencil(1, changedStencil);
// if (BGFX_STENCIL_FUNC_RMASK_MASK & bchanged)
// {
// uint32_t wmask = (bstencil&BGFX_STENCIL_FUNC_RMASK_MASK)>>BGFX_STENCIL_FUNC_RMASK_SHIFT;
2012-11-25 18:24:50 -08:00
// GL_CHECK(glStencilMask(wmask) );
2012-11-10 19:59:23 -08:00
// }
2012-12-26 22:52:10 -08:00
2015-04-07 17:58:14 -07:00
for ( uint8_t ii = 0 , num = frontAndBack + 1 ; ii < num ; + + ii )
2012-12-26 22:52:10 -08:00
{
uint32_t stencil = unpackStencil ( ii , newStencil ) ;
uint32_t changed = unpackStencil ( ii , changedStencil ) ;
GLenum face = s_stencilFace [ frontAndBack + ii ] ;
2012-11-10 19:59:23 -08:00
if ( ( BGFX_STENCIL_TEST_MASK | BGFX_STENCIL_FUNC_REF_MASK | BGFX_STENCIL_FUNC_RMASK_MASK ) & changed )
{
GLint ref = ( stencil & BGFX_STENCIL_FUNC_REF_MASK ) > > BGFX_STENCIL_FUNC_REF_SHIFT ;
GLint mask = ( stencil & BGFX_STENCIL_FUNC_RMASK_MASK ) > > BGFX_STENCIL_FUNC_RMASK_SHIFT ;
uint32_t func = ( stencil & BGFX_STENCIL_TEST_MASK ) > > BGFX_STENCIL_TEST_SHIFT ;
2015-07-16 20:28:43 -07:00
GL_CHECK ( glStencilFuncSeparate ( face , s_cmpFunc [ func ] , ref , mask ) ) ;
2012-11-10 19:59:23 -08:00
}
if ( ( BGFX_STENCIL_OP_FAIL_S_MASK | BGFX_STENCIL_OP_FAIL_Z_MASK | BGFX_STENCIL_OP_PASS_Z_MASK ) & changed )
{
uint32_t sfail = ( stencil & BGFX_STENCIL_OP_FAIL_S_MASK ) > > BGFX_STENCIL_OP_FAIL_S_SHIFT ;
uint32_t zfail = ( stencil & BGFX_STENCIL_OP_FAIL_Z_MASK ) > > BGFX_STENCIL_OP_FAIL_Z_SHIFT ;
uint32_t zpass = ( stencil & BGFX_STENCIL_OP_PASS_Z_MASK ) > > BGFX_STENCIL_OP_PASS_Z_SHIFT ;
GL_CHECK ( glStencilOpSeparate ( face , s_stencilOp [ sfail ] , s_stencilOp [ zfail ] , s_stencilOp [ zpass ] ) ) ;
}
2012-12-26 22:52:10 -08:00
}
2012-11-10 19:59:23 -08:00
}
else
{
2012-12-26 22:52:10 -08:00
GL_CHECK ( glDisable ( GL_STENCIL_TEST ) ) ;
}
2012-11-10 19:59:23 -08:00
}
2013-06-17 22:11:45 -07:00
if ( ( 0
| BGFX_STATE_CULL_MASK
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_DEPTH_TEST_MASK
| BGFX_STATE_RGB_WRITE
2014-03-25 23:07:51 -07:00
| BGFX_STATE_ALPHA_WRITE
2013-06-17 22:11:45 -07:00
| BGFX_STATE_BLEND_MASK
| BGFX_STATE_BLEND_EQUATION_MASK
| BGFX_STATE_ALPHA_REF_MASK
| BGFX_STATE_PT_MASK
| BGFX_STATE_POINT_SIZE_MASK
| BGFX_STATE_MSAA
2016-03-16 20:04:06 -07:00
| BGFX_STATE_LINEAA
| BGFX_STATE_CONSERVATIVE_RASTER
2013-06-17 22:11:45 -07:00
) & changedFlags )
2012-07-08 19:10:07 -07:00
{
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 ) ) ;
2014-02-23 11:21:23 -08:00
GL_CHECK ( glDepthFunc ( s_cmpFunc [ func ] ) ) ;
2012-07-08 19:10:07 -07:00
}
else
{
GL_CHECK ( glDisable ( GL_DEPTH_TEST ) ) ;
}
}
2013-03-08 21:54:08 -08:00
if ( BGFX_STATE_ALPHA_REF_MASK & changedFlags )
2012-07-08 19:10:07 -07:00
{
uint32_t ref = ( newFlags & BGFX_STATE_ALPHA_REF_MASK ) > > BGFX_STATE_ALPHA_REF_SHIFT ;
2014-12-27 19:00:41 -08:00
viewState . m_alphaRef = ref / 255.0f ;
2012-07-08 19:10:07 -07:00
}
# if BGFX_CONFIG_RENDERER_OPENGL
if ( ( BGFX_STATE_PT_POINTS | BGFX_STATE_POINT_SIZE_MASK ) & changedFlags )
{
2013-08-03 22:15:13 -07:00
float pointSize = ( float ) ( bx : : uint32_max ( 1 , ( newFlags & BGFX_STATE_POINT_SIZE_MASK ) > > BGFX_STATE_POINT_SIZE_SHIFT ) ) ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glPointSize ( pointSize ) ) ;
}
2013-02-17 20:42:33 -08:00
if ( BGFX_STATE_MSAA & changedFlags )
{
2016-03-16 20:04:06 -07:00
GL_CHECK ( BGFX_STATE_MSAA & newFlags
? glEnable ( GL_MULTISAMPLE )
: glDisable ( GL_MULTISAMPLE )
) ;
2013-02-17 20:42:33 -08:00
}
2016-03-16 15:09:15 -07:00
if ( BGFX_STATE_LINEAA & changedFlags )
{
2016-03-16 20:04:06 -07:00
GL_CHECK ( BGFX_STATE_LINEAA & newFlags
? glEnable ( GL_LINE_SMOOTH )
: glDisable ( GL_LINE_SMOOTH )
) ;
}
if ( m_conservativeRasterSupport
& & BGFX_STATE_CONSERVATIVE_RASTER & changedFlags )
{
GL_CHECK ( BGFX_STATE_CONSERVATIVE_RASTER & newFlags
? glEnable ( GL_CONSERVATIVE_RASTERIZATION_NV )
: glDisable ( GL_CONSERVATIVE_RASTERIZATION_NV )
) ;
2016-03-16 15:09:15 -07:00
}
2012-07-08 19:10:07 -07:00
# 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 ) ) ;
}
2016-03-16 15:09:15 -07:00
if ( ( ( 0
| BGFX_STATE_BLEND_MASK
| BGFX_STATE_BLEND_EQUATION_MASK
| BGFX_STATE_BLEND_INDEPENDENT
| BGFX_STATE_BLEND_ALPHA_TO_COVERAGE
) & changedFlags )
2014-07-20 20:27:13 -07:00
| | blendFactor ! = draw . m_rgba )
2012-07-08 19:10:07 -07:00
{
2016-03-16 20:04:06 -07:00
if ( m_atocSupport )
2016-03-16 15:09:15 -07:00
{
2016-03-16 20:04:06 -07:00
if ( BGFX_STATE_BLEND_ALPHA_TO_COVERAGE & newFlags )
{
GL_CHECK ( glEnable ( GL_SAMPLE_ALPHA_TO_COVERAGE ) ) ;
}
else
{
GL_CHECK ( glDisable ( GL_SAMPLE_ALPHA_TO_COVERAGE ) ) ;
}
2016-03-16 15:09:15 -07:00
}
if ( ( ( 0
| BGFX_STATE_BLEND_MASK
| BGFX_STATE_BLEND_EQUATION_MASK
| BGFX_STATE_BLEND_INDEPENDENT ) & newFlags )
2014-07-20 20:27:13 -07:00
| | blendFactor ! = draw . m_rgba )
2012-07-08 19:10:07 -07:00
{
2014-03-25 23:07:51 -07:00
const bool enabled = ! ! ( BGFX_STATE_BLEND_MASK & newFlags ) ;
2014-03-26 23:37:01 -07:00
const bool independent = ! ! ( BGFX_STATE_BLEND_INDEPENDENT & newFlags )
& & blendIndependentSupported
;
2014-03-25 23:07:51 -07:00
2015-03-29 22:40:35 -07:00
const uint32_t blend = uint32_t ( ( newFlags & BGFX_STATE_BLEND_MASK ) > > BGFX_STATE_BLEND_SHIFT ) ;
const uint32_t srcRGB = ( blend ) & 0xf ;
const uint32_t dstRGB = ( blend > > 4 ) & 0xf ;
const uint32_t srcA = ( blend > > 8 ) & 0xf ;
const uint32_t dstA = ( blend > > 12 ) & 0xf ;
2013-03-29 22:58:50 -07:00
2015-07-16 20:28:43 -07:00
const uint32_t equ = uint32_t ( ( newFlags & BGFX_STATE_BLEND_EQUATION_MASK ) > > BGFX_STATE_BLEND_EQUATION_SHIFT ) ;
2015-03-29 22:40:35 -07:00
const uint32_t equRGB = ( equ ) & 0x7 ;
const uint32_t equA = ( equ > > 3 ) & 0x7 ;
2013-03-29 22:58:50 -07:00
2014-07-20 20:27:13 -07:00
const uint32_t numRt = getNumRt ( ) ;
2014-03-25 23:07:51 -07:00
if ( ! BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
| | 1 > = numRt
| | ! independent )
{
if ( enabled )
{
GL_CHECK ( glEnable ( GL_BLEND ) ) ;
GL_CHECK ( glBlendFuncSeparate ( s_blendFactor [ srcRGB ] . m_src
, s_blendFactor [ dstRGB ] . m_dst
, s_blendFactor [ srcA ] . m_src
2014-03-27 21:35:14 -07:00
, s_blendFactor [ dstA ] . m_dst
) ) ;
2014-03-25 23:07:51 -07:00
GL_CHECK ( glBlendEquationSeparate ( s_blendEquation [ equRGB ] , s_blendEquation [ equA ] ) ) ;
if ( ( s_blendFactor [ srcRGB ] . m_factor | | s_blendFactor [ dstRGB ] . m_factor )
2014-07-20 20:27:13 -07:00
& & blendFactor ! = draw . m_rgba )
2014-03-25 23:07:51 -07:00
{
2014-07-20 20:27:13 -07:00
const uint32_t rgba = draw . m_rgba ;
2014-03-25 23:07:51 -07:00
GLclampf rr = ( ( rgba > > 24 ) ) / 255.0f ;
GLclampf gg = ( ( rgba > > 16 ) & 0xff ) / 255.0f ;
GLclampf bb = ( ( rgba > > 8 ) & 0xff ) / 255.0f ;
GLclampf aa = ( ( rgba ) & 0xff ) / 255.0f ;
GL_CHECK ( glBlendColor ( rr , gg , bb , aa ) ) ;
}
}
else
{
GL_CHECK ( glDisable ( GL_BLEND ) ) ;
}
}
else
{
if ( enabled )
{
GL_CHECK ( glEnablei ( GL_BLEND , 0 ) ) ;
GL_CHECK ( glBlendFuncSeparatei ( 0
, s_blendFactor [ srcRGB ] . m_src
, s_blendFactor [ dstRGB ] . m_dst
, s_blendFactor [ srcA ] . m_src
2014-03-27 21:35:14 -07:00
, s_blendFactor [ dstA ] . m_dst
) ) ;
2014-03-25 23:07:51 -07:00
GL_CHECK ( glBlendEquationSeparatei ( 0
, s_blendEquation [ equRGB ]
2014-03-27 21:35:14 -07:00
, s_blendEquation [ equA ]
) ) ;
2014-03-25 23:07:51 -07:00
}
else
{
GL_CHECK ( glDisablei ( GL_BLEND , 0 ) ) ;
}
2014-07-20 20:27:13 -07:00
for ( uint32_t ii = 1 , rgba = draw . m_rgba ; ii < numRt ; + + ii , rgba > > = 11 )
2014-03-25 23:07:51 -07:00
{
if ( 0 ! = ( rgba & 0x7ff ) )
{
const uint32_t src = ( rgba ) & 0xf ;
const uint32_t dst = ( rgba > > 4 ) & 0xf ;
const uint32_t equation = ( rgba > > 8 ) & 0x7 ;
GL_CHECK ( glEnablei ( GL_BLEND , ii ) ) ;
GL_CHECK ( glBlendFunci ( ii , s_blendFactor [ src ] . m_src , s_blendFactor [ dst ] . m_dst ) ) ;
GL_CHECK ( glBlendEquationi ( ii , s_blendEquation [ equation ] ) ) ;
}
else
{
GL_CHECK ( glDisablei ( GL_BLEND , ii ) ) ;
}
}
2013-03-29 22:58:50 -07:00
}
2012-07-08 19:10:07 -07:00
}
else
{
GL_CHECK ( glDisable ( GL_BLEND ) ) ;
}
2014-03-25 23:07:51 -07:00
2014-07-20 20:27:13 -07:00
blendFactor = draw . m_rgba ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
const uint64_t pt = _render - > m_debug & BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : newFlags & BGFX_STATE_PT_MASK ;
2014-04-26 23:48:41 -07:00
primIndex = uint8_t ( pt > > BGFX_STATE_PT_SHIFT ) ;
prim = s_primInfo [ primIndex ] ;
2012-07-08 19:10:07 -07:00
}
2012-09-16 17:36:08 -07:00
bool programChanged = false ;
2014-07-20 20:27:13 -07:00
bool constantsChanged = draw . m_constBegin < draw . m_constEnd ;
2012-07-08 19:10:07 -07:00
bool bindAttribs = false ;
2015-09-14 15:53:33 -07:00
rendererUpdateUniforms ( this , _render - > m_uniformBuffer , draw . m_constBegin , draw . m_constEnd ) ;
2012-07-08 19:10:07 -07:00
2012-09-16 17:36:08 -07:00
if ( key . m_program ! = programIdx )
2012-07-08 19:10:07 -07:00
{
2012-09-16 17:36:08 -07:00
programIdx = key . m_program ;
2014-07-20 20:27:13 -07:00
GLuint id = invalidHandle = = programIdx ? 0 : m_program [ programIdx ] . m_id ;
2015-04-09 20:36:52 -07:00
// Skip rendering if program index is valid, but program is invalid.
programIdx = 0 = = id ? invalidHandle : programIdx ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glUseProgram ( id ) ) ;
2014-01-08 22:08:37 -08:00
programChanged =
constantsChanged =
2012-07-08 19:10:07 -07:00
bindAttribs = true ;
}
2012-09-16 17:36:08 -07:00
if ( invalidHandle ! = programIdx )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
ProgramGL & program = m_program [ programIdx ] ;
2012-07-08 19:10:07 -07:00
2014-10-08 19:58:29 -07:00
if ( constantsChanged
& & NULL ! = program . m_constantBuffer )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
commit ( * program . m_constantBuffer ) ;
2012-07-08 19:10:07 -07:00
}
2014-12-27 19:00:41 -08:00
viewState . setPredefined < 1 > ( this , view , eye , program , _render , draw ) ;
2012-07-08 19:10:07 -07:00
{
2014-07-30 20:37:54 -07:00
for ( uint32_t stage = 0 ; stage < BGFX_CONFIG_MAX_TEXTURE_SAMPLERS ; + + stage )
2012-07-08 19:10:07 -07:00
{
2015-08-28 20:34:14 -07:00
const Binding & bind = draw . m_bind [ stage ] ;
2015-01-13 22:34:48 -08:00
Binding & current = currentState . m_bind [ stage ] ;
2015-08-28 20:34:14 -07:00
if ( current . m_idx ! = bind . m_idx
2015-11-01 17:28:23 -08:00
| | current . m_un . m_draw . m_textureFlags ! = bind . m_un . m_draw . m_textureFlags
2012-09-16 17:36:08 -07:00
| | programChanged )
2012-07-08 19:10:07 -07:00
{
2015-08-28 20:34:14 -07:00
if ( invalidHandle ! = bind . m_idx )
2012-07-08 19:10:07 -07:00
{
2015-08-28 20:34:14 -07:00
TextureGL & texture = m_textures [ bind . m_idx ] ;
2015-11-01 17:28:23 -08:00
texture . commit ( stage , bind . m_un . m_draw . m_textureFlags , _render - > m_colorPalette ) ;
2012-07-08 19:10:07 -07:00
}
}
2015-08-28 20:34:14 -07:00
current = bind ;
2012-07-08 19:10:07 -07:00
}
}
2013-03-03 22:30:50 -08:00
if ( 0 ! = defaultVao
2014-07-20 20:27:13 -07:00
& & 0 = = draw . m_startVertex
& & 0 = = draw . m_instanceDataOffset )
2012-07-08 19:10:07 -07:00
{
2013-01-12 19:13:51 -08:00
if ( programChanged
2015-02-06 10:47:53 -08:00
| | baseVertex ! = draw . m_startVertex
| | currentState . m_vertexBuffer . idx ! = draw . m_vertexBuffer . idx
| | currentState . m_indexBuffer . idx ! = draw . m_indexBuffer . idx
2014-07-20 20:27:13 -07:00
| | currentState . m_instanceDataOffset ! = draw . m_instanceDataOffset
2015-02-06 10:47:53 -08:00
| | currentState . m_instanceDataStride ! = draw . m_instanceDataStride
| | currentState . m_instanceDataBuffer . idx ! = draw . m_instanceDataBuffer . idx )
2012-07-08 19:10:07 -07:00
{
2013-01-21 23:36:47 -08:00
bx : : HashMurmur2A murmur ;
murmur . begin ( ) ;
2014-07-20 20:27:13 -07:00
murmur . add ( draw . m_vertexBuffer . idx ) ;
2014-12-06 18:12:40 -08:00
if ( isValid ( draw . m_vertexBuffer ) )
{
const VertexBufferGL & vb = m_vertexBuffers [ draw . m_vertexBuffer . idx ] ;
uint16_t decl = ! isValid ( vb . m_decl ) ? draw . m_vertexDecl . idx : vb . m_decl . idx ;
murmur . add ( decl ) ;
}
2014-07-20 20:27:13 -07:00
murmur . add ( draw . m_indexBuffer . idx ) ;
murmur . add ( draw . m_instanceDataBuffer . idx ) ;
murmur . add ( draw . m_instanceDataOffset ) ;
murmur . add ( draw . m_instanceDataStride ) ;
2013-01-21 23:36:47 -08:00
murmur . add ( programIdx ) ;
uint32_t hash = murmur . end ( ) ;
2013-01-12 19:13:51 -08:00
2014-07-20 20:27:13 -07:00
currentState . m_vertexBuffer = draw . m_vertexBuffer ;
currentState . m_indexBuffer = draw . m_indexBuffer ;
currentState . m_instanceDataOffset = draw . m_instanceDataOffset ;
currentState . m_instanceDataStride = draw . m_instanceDataStride ;
baseVertex = draw . m_startVertex ;
2013-01-12 19:13:51 -08:00
2014-07-20 20:27:13 -07:00
GLuint id = m_vaoStateCache . find ( hash ) ;
2013-01-12 19:13:51 -08:00
if ( UINT32_MAX ! = id )
{
2013-01-21 23:36:47 -08:00
currentVao = id ;
2013-01-12 19:13:51 -08:00
GL_CHECK ( glBindVertexArray ( id ) ) ;
}
else
{
2014-07-20 20:27:13 -07:00
id = m_vaoStateCache . add ( hash ) ;
2013-01-21 23:36:47 -08:00
currentVao = id ;
2013-01-12 19:13:51 -08:00
GL_CHECK ( glBindVertexArray ( id ) ) ;
2013-01-21 23:36:47 -08:00
program . add ( hash ) ;
2014-07-20 20:27:13 -07:00
if ( isValid ( draw . m_vertexBuffer ) )
2013-01-12 19:13:51 -08:00
{
2014-07-20 20:27:13 -07:00
VertexBufferGL & vb = m_vertexBuffers [ draw . m_vertexBuffer . idx ] ;
2013-01-21 23:36:47 -08:00
vb . add ( hash ) ;
2013-01-12 19:13:51 -08:00
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , vb . m_id ) ) ;
2014-07-20 20:27:13 -07:00
uint16_t decl = ! isValid ( vb . m_decl ) ? draw . m_vertexDecl . idx : vb . m_decl . idx ;
program . bindAttributes ( m_vertexDecls [ decl ] , draw . m_startVertex ) ;
2013-01-12 19:13:51 -08:00
2014-07-20 20:27:13 -07:00
if ( isValid ( draw . m_instanceDataBuffer ) )
2013-01-12 19:13:51 -08:00
{
2014-07-20 20:27:13 -07:00
VertexBufferGL & instanceVb = m_vertexBuffers [ draw . m_instanceDataBuffer . idx ] ;
2013-01-21 23:36:47 -08:00
instanceVb . add ( hash ) ;
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , instanceVb . m_id ) ) ;
2014-07-20 20:27:13 -07:00
program . bindInstanceData ( draw . m_instanceDataStride , draw . m_instanceDataOffset ) ;
2013-01-12 19:13:51 -08:00
}
}
else
{
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ) ;
}
2014-07-20 20:27:13 -07:00
if ( isValid ( draw . m_indexBuffer ) )
2013-01-12 19:13:51 -08:00
{
2014-07-20 20:27:13 -07:00
IndexBufferGL & ib = m_indexBuffers [ draw . m_indexBuffer . idx ] ;
2013-01-21 23:36:47 -08:00
ib . add ( hash ) ;
2013-01-12 19:13:51 -08:00
GL_CHECK ( glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , ib . m_id ) ) ;
}
else
{
GL_CHECK ( glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ) ;
}
}
2012-07-08 19:10:07 -07:00
}
}
2013-01-12 19:13:51 -08:00
else
2012-07-08 19:10:07 -07:00
{
2013-03-03 22:30:50 -08:00
if ( 0 ! = defaultVao
2013-01-21 23:36:47 -08:00
& & 0 ! = currentVao )
{
2013-03-03 22:30:50 -08:00
GL_CHECK ( glBindVertexArray ( defaultVao ) ) ;
2013-01-21 23:36:47 -08:00
currentState . m_vertexBuffer . idx = invalidHandle ;
currentState . m_indexBuffer . idx = invalidHandle ;
bindAttribs = true ;
currentVao = 0 ;
}
2013-01-12 19:13:51 -08:00
if ( programChanged
2014-07-20 20:27:13 -07:00
| | currentState . m_vertexBuffer . idx ! = draw . m_vertexBuffer . idx
| | currentState . m_instanceDataBuffer . idx ! = draw . m_instanceDataBuffer . idx
| | currentState . m_instanceDataOffset ! = draw . m_instanceDataOffset
| | currentState . m_instanceDataStride ! = draw . m_instanceDataStride )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
currentState . m_vertexBuffer = draw . m_vertexBuffer ;
currentState . m_instanceDataBuffer . idx = draw . m_instanceDataBuffer . idx ;
currentState . m_instanceDataOffset = draw . m_instanceDataOffset ;
currentState . m_instanceDataStride = draw . m_instanceDataStride ;
2013-01-12 19:13:51 -08:00
2014-07-20 20:27:13 -07:00
uint16_t handle = draw . m_vertexBuffer . idx ;
2013-01-12 19:13:51 -08:00
if ( invalidHandle ! = handle )
{
2014-07-20 20:27:13 -07:00
VertexBufferGL & vb = m_vertexBuffers [ handle ] ;
2013-01-12 19:13:51 -08:00
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , vb . m_id ) ) ;
bindAttribs = true ;
}
else
{
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , 0 ) ) ;
}
2012-07-08 19:10:07 -07:00
}
2013-01-12 19:13:51 -08:00
2014-07-20 20:27:13 -07:00
if ( currentState . m_indexBuffer . idx ! = draw . m_indexBuffer . idx )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
currentState . m_indexBuffer = draw . m_indexBuffer ;
2013-01-12 19:13:51 -08:00
2014-07-20 20:27:13 -07:00
uint16_t handle = draw . m_indexBuffer . idx ;
2013-01-12 19:13:51 -08:00
if ( invalidHandle ! = handle )
{
2014-07-20 20:27:13 -07:00
IndexBufferGL & ib = m_indexBuffers [ handle ] ;
2013-01-12 19:13:51 -08:00
GL_CHECK ( glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , ib . m_id ) ) ;
}
else
{
GL_CHECK ( glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , 0 ) ) ;
}
2012-07-08 19:10:07 -07:00
}
2013-09-29 21:33:50 -07:00
if ( isValid ( currentState . m_vertexBuffer ) )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
if ( baseVertex ! = draw . m_startVertex
2013-01-12 19:13:51 -08:00
| | bindAttribs )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
baseVertex = draw . m_startVertex ;
const VertexBufferGL & vb = m_vertexBuffers [ draw . m_vertexBuffer . idx ] ;
uint16_t decl = ! isValid ( vb . m_decl ) ? draw . m_vertexDecl . idx : vb . m_decl . idx ;
program . bindAttributes ( m_vertexDecls [ decl ] , draw . m_startVertex ) ;
2013-01-12 19:13:51 -08:00
2014-07-20 20:27:13 -07:00
if ( isValid ( draw . m_instanceDataBuffer ) )
2013-01-12 19:13:51 -08:00
{
2014-07-20 20:27:13 -07:00
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , m_vertexBuffers [ draw . m_instanceDataBuffer . idx ] . m_id ) ) ;
program . bindInstanceData ( draw . m_instanceDataStride , draw . m_instanceDataOffset ) ;
2013-01-12 19:13:51 -08:00
}
2012-07-08 19:10:07 -07:00
}
}
2013-01-12 19:13:51 -08:00
}
2012-07-08 19:10:07 -07:00
2013-09-29 21:33:50 -07:00
if ( isValid ( currentState . m_vertexBuffer ) )
2013-01-12 19:13:51 -08:00
{
2014-07-20 20:27:13 -07:00
uint32_t numVertices = draw . m_numVertices ;
2013-09-29 10:42:41 -07:00
if ( UINT32_MAX = = numVertices )
2012-11-03 13:12:26 -07:00
{
2014-07-20 20:27:13 -07:00
const VertexBufferGL & vb = m_vertexBuffers [ currentState . m_vertexBuffer . idx ] ;
uint16_t decl = ! isValid ( vb . m_decl ) ? draw . m_vertexDecl . idx : vb . m_decl . idx ;
const VertexDecl & vertexDecl = m_vertexDecls [ decl ] ;
2012-11-03 13:12:26 -07:00
numVertices = vb . m_size / vertexDecl . m_stride ;
}
2015-04-30 18:06:41 -07:00
uint32_t numIndices = 0 ;
2012-07-08 19:10:07 -07:00
uint32_t numPrimsSubmitted = 0 ;
2015-04-30 18:06:41 -07:00
uint32_t numInstances = 0 ;
uint32_t numPrimsRendered = 0 ;
uint32_t numDrawIndirect = 0 ;
2012-07-08 19:10:07 -07:00
2015-11-01 19:12:42 -08:00
if ( hasOcclusionQuery )
{
2015-11-03 16:00:14 -08:00
m_occlusionQuery . begin ( _render , draw . m_occlusionQuery ) ;
2015-11-01 19:12:42 -08:00
}
2015-05-01 14:54:23 -07:00
if ( isValid ( draw . m_indirectBuffer ) )
2012-07-08 19:10:07 -07:00
{
2015-05-01 14:54:23 -07:00
const VertexBufferGL & vb = m_vertexBuffers [ draw . m_indirectBuffer . idx ] ;
if ( currentState . m_indirectBuffer . idx ! = draw . m_indirectBuffer . idx )
2015-04-30 18:06:41 -07:00
{
2015-05-01 14:54:23 -07:00
currentState . m_indirectBuffer = draw . m_indirectBuffer ;
2015-04-30 18:06:41 -07:00
GL_CHECK ( glBindBuffer ( GL_DRAW_INDIRECT_BUFFER , vb . m_id ) ) ;
}
2015-04-08 19:59:48 -07:00
2015-04-30 18:06:41 -07:00
if ( isValid ( draw . m_indexBuffer ) )
2012-07-08 19:10:07 -07:00
{
2015-04-30 18:06:41 -07:00
const IndexBufferGL & ib = m_indexBuffers [ draw . m_indexBuffer . idx ] ;
const bool hasIndex16 = 0 = = ( ib . m_flags & BGFX_BUFFER_INDEX32 ) ;
const GLenum indexFormat = hasIndex16
? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
;
2015-05-01 14:54:23 -07:00
numDrawIndirect = UINT16_MAX = = draw . m_numIndirect
? vb . m_size / BGFX_CONFIG_DRAW_INDIRECT_STRIDE
: draw . m_numIndirect
;
2015-04-30 18:06:41 -07:00
2015-05-01 14:54:23 -07:00
uintptr_t args = draw . m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE ;
GL_CHECK ( glMultiDrawElementsIndirect ( prim . m_type , indexFormat
, ( void * ) args
, numDrawIndirect
, BGFX_CONFIG_DRAW_INDIRECT_STRIDE
) ) ;
2012-07-08 19:10:07 -07:00
}
2015-04-30 18:06:41 -07:00
else
2012-07-08 19:10:07 -07:00
{
2015-05-01 14:54:23 -07:00
numDrawIndirect = UINT16_MAX = = draw . m_numIndirect
? vb . m_size / BGFX_CONFIG_DRAW_INDIRECT_STRIDE
: draw . m_numIndirect
;
2012-07-08 19:10:07 -07:00
2015-05-01 14:54:23 -07:00
uintptr_t args = draw . m_startIndirect * BGFX_CONFIG_DRAW_INDIRECT_STRIDE ;
GL_CHECK ( glMultiDrawArraysIndirect ( prim . m_type
, ( void * ) args
, numDrawIndirect
, BGFX_CONFIG_DRAW_INDIRECT_STRIDE
) ) ;
2012-07-08 19:10:07 -07:00
}
}
else
{
2015-05-01 14:54:23 -07:00
if ( isValid ( currentState . m_indirectBuffer ) )
2015-04-30 18:06:41 -07:00
{
2015-05-01 14:54:23 -07:00
currentState . m_indirectBuffer . idx = invalidHandle ;
2015-04-30 18:06:41 -07:00
GL_CHECK ( glBindBuffer ( GL_DRAW_INDIRECT_BUFFER , 0 ) ) ;
}
2012-07-08 19:10:07 -07:00
2015-04-30 18:06:41 -07:00
if ( isValid ( draw . m_indexBuffer ) )
{
const IndexBufferGL & ib = m_indexBuffers [ draw . m_indexBuffer . idx ] ;
const bool hasIndex16 = 0 = = ( ib . m_flags & BGFX_BUFFER_INDEX32 ) ;
2015-07-02 17:05:51 -07:00
const uint32_t indexSize = hasIndex16 ? 2 : 4 ;
2015-04-30 18:06:41 -07:00
const GLenum indexFormat = hasIndex16
? GL_UNSIGNED_SHORT
: GL_UNSIGNED_INT
;
if ( UINT32_MAX = = draw . m_numIndices )
{
numIndices = ib . m_size / indexSize ;
numPrimsSubmitted = numIndices / prim . m_div - prim . m_sub ;
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
GL_CHECK ( glDrawElementsInstanced ( prim . m_type
, numIndices
, indexFormat
, ( void * ) 0
, draw . m_numInstances
) ) ;
}
else if ( prim . m_min < = draw . m_numIndices )
{
numIndices = draw . m_numIndices ;
numPrimsSubmitted = numIndices / prim . m_div - prim . m_sub ;
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
GL_CHECK ( glDrawElementsInstanced ( prim . m_type
, numIndices
, indexFormat
2015-07-02 17:05:51 -07:00
, ( void * ) ( uintptr_t ) ( draw . m_startIndex * indexSize )
2015-04-30 18:06:41 -07:00
, draw . m_numInstances
) ) ;
}
}
else
{
numPrimsSubmitted = numVertices / prim . m_div - prim . m_sub ;
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
GL_CHECK ( glDrawArraysInstanced ( prim . m_type
, 0
, numVertices
, draw . m_numInstances
) ) ;
}
2012-07-08 19:10:07 -07:00
}
2015-11-01 19:12:42 -08:00
if ( hasOcclusionQuery )
{
m_occlusionQuery . end ( ) ;
}
2014-04-26 23:48:41 -07:00
statsNumPrimsSubmitted [ primIndex ] + = numPrimsSubmitted ;
statsNumPrimsRendered [ primIndex ] + = numPrimsRendered ;
statsNumInstances [ primIndex ] + = numInstances ;
2012-07-08 19:10:07 -07:00
statsNumIndices + = numIndices ;
}
}
}
2013-01-01 13:19:10 -08:00
2014-07-20 20:27:13 -07:00
blitMsaaFbo ( ) ;
2013-02-21 22:05:33 -08:00
2016-01-14 23:47:56 -08:00
if ( m_vaoSupport )
{
GL_CHECK ( glBindVertexArray ( m_vao ) ) ;
}
2016-01-15 08:28:36 +01:00
2014-05-26 14:09:26 -07:00
if ( 0 < _render - > m_num )
2013-01-01 13:19:10 -08:00
{
2015-05-15 13:14:35 -07:00
if ( 0 ! = ( m_resolution . m_flags & BGFX_RESET_FLUSH_AFTER_RENDER ) )
{
GL_CHECK ( glFlush ( ) ) ;
}
2013-01-01 13:19:10 -08:00
captureElapsed = - bx : : getHPCounter ( ) ;
2014-07-20 20:27:13 -07:00
capture ( ) ;
2013-01-01 13:19:10 -08:00
captureElapsed + = bx : : getHPCounter ( ) ;
2015-11-16 10:42:56 -04:00
BGFX_GPU_PROFILER_END ( ) ;
BGFX_PROFILER_END ( ) ;
2013-01-01 13:19:10 -08:00
}
2012-07-08 19:10:07 -07:00
}
2015-11-16 10:42:56 -04:00
BGFX_GPU_PROFILER_END ( ) ;
2014-09-07 17:17:38 -07:00
m_glctx . makeCurrent ( NULL ) ;
2012-07-08 19:10:07 -07:00
int64_t now = bx : : getHPCounter ( ) ;
elapsed + = now ;
static int64_t last = now ;
2015-11-09 17:56:12 -08:00
Stats & perfStats = _render - > m_perfStats ;
perfStats . cpuTimeBegin = last ;
2012-07-08 19:10:07 -07:00
int64_t frameTime = now - last ;
last = now ;
2012-08-05 14:51:49 -07:00
static int64_t min = frameTime ;
static int64_t max = frameTime ;
min = min > frameTime ? frameTime : min ;
max = max < frameTime ? frameTime : max ;
2015-08-16 15:37:46 -07:00
static uint32_t maxGpuLatency = 0 ;
static double maxGpuElapsed = 0.0f ;
2015-07-22 18:05:11 -07:00
double elapsedGpuMs = 0.0 ;
uint64_t elapsedGl = 0 ;
2015-08-16 15:37:46 -07:00
2015-07-22 18:05:11 -07:00
if ( m_timerQuerySupport )
2012-07-08 19:10:07 -07:00
{
2015-08-16 15:37:46 -07:00
m_gpuTimer . end ( ) ;
while ( m_gpuTimer . get ( ) )
{
elapsedGl = m_gpuTimer . m_elapsed ;
elapsedGpuMs = double ( elapsedGl ) / 1e6 ;
maxGpuElapsed = elapsedGpuMs > maxGpuElapsed ? elapsedGpuMs : maxGpuElapsed ;
}
maxGpuLatency = bx : : uint32_imax ( maxGpuLatency , m_gpuTimer . m_control . available ( ) - 1 ) ;
2015-07-22 18:05:11 -07:00
}
const int64_t timerFreq = bx : : getHPFrequency ( ) ;
2015-11-09 17:56:12 -08:00
perfStats . cpuTimeEnd = now ;
2015-07-22 18:05:11 -07:00
perfStats . cpuTimerFreq = timerFreq ;
2015-11-09 17:56:12 -08:00
perfStats . gpuTimeBegin = m_gpuTimer . m_begin ;
perfStats . gpuTimeEnd = m_gpuTimer . m_end ;
2015-09-02 15:03:22 -07:00
perfStats . gpuTimerFreq = 1000000000 ;
2012-07-08 19:10:07 -07:00
2015-07-22 18:05:11 -07:00
if ( _render - > m_debug & ( BGFX_DEBUG_IFH | BGFX_DEBUG_STATS ) )
{
2014-07-20 20:27:13 -07:00
TextVideoMem & tvm = m_textVideoMem ;
2012-07-08 19:10:07 -07:00
static int64_t next = now ;
if ( now > = next )
{
2015-07-22 18:05:11 -07:00
next = now + timerFreq ;
double freq = double ( timerFreq ) ;
2012-07-08 19:10:07 -07:00
double toMs = 1000.0 / freq ;
tvm . clear ( ) ;
2013-04-20 23:13:44 -07:00
uint16_t pos = 0 ;
2014-05-26 14:09:26 -07:00
tvm . printf ( 0 , pos + + , BGFX_CONFIG_DEBUG ? 0x89 : 0x8f , " %s / " BX_COMPILER_NAME " / " BX_CPU_NAME " / " BX_ARCH_NAME " / " BX_PLATFORM_NAME " "
, getRendererName ( )
) ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 0 , pos + + , 0x8f , " Vendor: %s " , m_vendor ) ;
tvm . printf ( 0 , pos + + , 0x8f , " Renderer: %s " , m_renderer ) ;
tvm . printf ( 0 , pos + + , 0x8f , " Version: %s " , m_version ) ;
tvm . printf ( 0 , pos + + , 0x8f , " GLSL version: %s " , m_glslVersion ) ;
2013-04-20 23:13:44 -07:00
2015-09-09 17:26:55 -07:00
char processMemoryUsed [ 16 ] ;
bx : : prettify ( processMemoryUsed , BX_COUNTOF ( processMemoryUsed ) , bx : : getProcessMemoryUsed ( ) ) ;
2015-09-09 18:35:59 -07:00
tvm . printf ( 0 , pos + + , 0x8f , " Memory: %s (process) " , processMemoryUsed ) ;
2015-09-09 17:26:55 -07:00
2013-04-20 23:13:44 -07:00
pos = 10 ;
2015-12-03 14:39:26 -08:00
tvm . printf ( 10 , pos + + , 0x8e , " Frame: %7.3f, % 7.3f \x1f , % 7.3f \x1e [ms] / % 6.2f FPS "
2012-08-05 14:51:49 -07:00
, double ( frameTime ) * toMs
, double ( min ) * toMs
, double ( max ) * toMs
, freq / frameTime
2014-02-05 23:07:11 -08:00
) ;
2014-10-28 22:08:55 -07:00
char hmd [ 16 ] ;
bx : : snprintf ( hmd , BX_COUNTOF ( hmd ) , " , [%c] HMD " , hmdEnabled ? ' \xfe ' : ' ' ) ;
2014-02-05 23:07:11 -08:00
const uint32_t msaa = ( m_resolution . m_flags & BGFX_RESET_MSAA_MASK ) > > BGFX_RESET_MSAA_SHIFT ;
2015-12-03 14:39:26 -08:00
tvm . printf ( 10 , pos + + , 0x8e , " Reset flags: [%c] vsync, [%c] MSAAx%d%s, [%c] MaxAnisotropy "
2014-02-05 23:07:11 -08:00
, ! ! ( m_resolution . m_flags & BGFX_RESET_VSYNC ) ? ' \xfe ' : ' '
, 0 ! = msaa ? ' \xfe ' : ' '
, 1 < < msaa
2014-10-28 22:08:55 -07:00
, m_ovr . isInitialized ( ) ? hmd : " , no-HMD "
2015-01-21 20:39:42 -08:00
, ! ! ( m_resolution . m_flags & BGFX_RESET_MAXANISOTROPY ) ? ' \xfe ' : ' '
2012-08-05 14:51:49 -07:00
) ;
2012-12-30 20:52:47 -08:00
double elapsedCpuMs = double ( elapsed ) * toMs ;
2015-12-03 14:39:26 -08:00
tvm . printf ( 10 , pos + + , 0x8e , " Submitted: %5d (draw %5d, compute %4d) / CPU %7.4f [ms] %c GPU %7.4f [ms] (latency %d) "
2014-05-26 14:09:26 -07:00
, _render - > m_num
2015-03-26 22:43:50 -07:00
, statsKeyType [ 0 ]
, statsKeyType [ 1 ]
2012-07-08 19:10:07 -07:00
, elapsedCpuMs
, elapsedCpuMs > elapsedGpuMs ? ' > ' : ' < '
2015-08-16 15:37:46 -07:00
, maxGpuElapsed
, maxGpuLatency
2012-07-08 19:10:07 -07:00
) ;
2015-08-16 15:37:46 -07:00
maxGpuLatency = 0 ;
maxGpuElapsed = 0.0 ;
2015-05-12 17:03:25 -07:00
2014-04-26 23:48:41 -07:00
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( s_primInfo ) ; + + ii )
{
2015-12-03 14:39:26 -08:00
tvm . printf ( 10 , pos + + , 0x8e , " %10s: %7d (#inst: %5d), submitted: %7d "
2014-04-26 23:48:41 -07:00
, s_primName [ ii ]
, statsNumPrimsRendered [ ii ]
, statsNumInstances [ ii ]
, statsNumPrimsSubmitted [ ii ]
) ;
}
2012-12-30 20:52:47 -08:00
2014-12-11 20:48:16 -08:00
if ( NULL ! = m_renderdocdll )
{
tvm . printf ( tvm . m_width - 27 , 0 , 0x1f , " [F11 - RenderDoc capture] " ) ;
}
2015-08-27 11:06:45 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Indices: %7d " , statsNumIndices ) ;
2015-09-14 15:53:33 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Uniform size: %7d, Max: %7d " , _render - > m_uniformEnd , _render - > m_uniformMax ) ;
2015-08-27 11:06:45 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " DVB size: %7d " , _render - > m_vboffset ) ;
tvm . printf ( 10 , pos + + , 0x8e , " DIB size: %7d " , _render - > m_iboffset ) ;
2012-07-08 19:10:07 -07:00
2014-10-05 00:14:21 -07:00
pos + + ;
tvm . printf ( 10 , pos + + , 0x8e , " State cache: " ) ;
tvm . printf ( 10 , pos + + , 0x8e , " VAO | Sampler " ) ;
tvm . printf ( 10 , pos + + , 0x8e , " %6d | %6d "
, m_vaoStateCache . getCount ( )
, m_samplerStateCache . getCount ( )
) ;
2014-04-26 23:48:41 -07:00
2012-07-24 21:54:19 -07:00
# if BGFX_CONFIG_RENDERER_OPENGL
if ( s_extension [ Extension : : ATI_meminfo ] . m_supported )
{
GLint vboFree [ 4 ] ;
2012-07-24 22:59:18 -07:00
GL_CHECK ( glGetIntegerv ( GL_VBO_FREE_MEMORY_ATI , vboFree ) ) ;
2012-07-24 21:54:19 -07:00
GLint texFree [ 4 ] ;
2012-07-24 22:59:18 -07:00
GL_CHECK ( glGetIntegerv ( GL_TEXTURE_FREE_MEMORY_ATI , texFree ) ) ;
2012-07-24 21:54:19 -07:00
GLint rbfFree [ 4 ] ;
2012-07-24 22:59:18 -07:00
GL_CHECK ( glGetIntegerv ( GL_RENDERBUFFER_FREE_MEMORY_ATI , rbfFree ) ) ;
2012-07-24 21:54:19 -07:00
pos + + ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , 0x8c , " -------------| free| free b| aux| aux fb " ) ;
2014-08-25 20:50:36 -07:00
char tmp0 [ 16 ] ;
char tmp1 [ 16 ] ;
char tmp2 [ 16 ] ;
char tmp3 [ 16 ] ;
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , vboFree [ 0 ] ) ;
bx : : prettify ( tmp1 , BX_COUNTOF ( tmp1 ) , vboFree [ 1 ] ) ;
bx : : prettify ( tmp2 , BX_COUNTOF ( tmp2 ) , vboFree [ 2 ] ) ;
bx : : prettify ( tmp3 , BX_COUNTOF ( tmp3 ) , vboFree [ 3 ] ) ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " VBO: %10s, %10s, %10s, %10s " , tmp0 , tmp1 , tmp2 , tmp3 ) ;
2014-08-25 20:50:36 -07:00
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , texFree [ 0 ] ) ;
bx : : prettify ( tmp1 , BX_COUNTOF ( tmp1 ) , texFree [ 1 ] ) ;
bx : : prettify ( tmp2 , BX_COUNTOF ( tmp2 ) , texFree [ 2 ] ) ;
bx : : prettify ( tmp3 , BX_COUNTOF ( tmp3 ) , texFree [ 3 ] ) ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Texture: %10s, %10s, %10s, %10s " , tmp0 , tmp1 , tmp2 , tmp3 ) ;
2014-08-25 20:50:36 -07:00
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , rbfFree [ 0 ] ) ;
bx : : prettify ( tmp1 , BX_COUNTOF ( tmp1 ) , rbfFree [ 1 ] ) ;
bx : : prettify ( tmp2 , BX_COUNTOF ( tmp2 ) , rbfFree [ 2 ] ) ;
bx : : prettify ( tmp3 , BX_COUNTOF ( tmp3 ) , rbfFree [ 3 ] ) ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Render Buffer: %10s, %10s, %10s, %10s " , tmp0 , tmp1 , tmp2 , tmp3 ) ;
2012-07-24 21:54:19 -07:00
}
else if ( s_extension [ Extension : : NVX_gpu_memory_info ] . m_supported )
{
2012-07-24 22:59:18 -07:00
GLint dedicated ;
GL_CHECK ( glGetIntegerv ( GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX , & dedicated ) ) ;
GLint totalAvail ;
GL_CHECK ( glGetIntegerv ( GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX , & totalAvail ) ) ;
GLint currAvail ;
GL_CHECK ( glGetIntegerv ( GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX , & currAvail ) ) ;
GLint evictedCount ;
GL_CHECK ( glGetIntegerv ( GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX , & evictedCount ) ) ;
GLint evictedMemory ;
GL_CHECK ( glGetIntegerv ( GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX , & evictedMemory ) ) ;
2015-08-16 15:37:46 -07:00
pos + + ;
2014-08-25 20:50:36 -07:00
char tmp0 [ 16 ] ;
char tmp1 [ 16 ] ;
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , dedicated ) ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Dedicated: %10s " , tmp0 ) ;
2014-08-25 20:50:36 -07:00
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , currAvail ) ;
bx : : prettify ( tmp1 , BX_COUNTOF ( tmp1 ) , totalAvail ) ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Available: %10s / %10s " , tmp0 , tmp1 ) ;
2014-08-25 20:50:36 -07:00
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , evictedCount ) ;
bx : : prettify ( tmp1 , BX_COUNTOF ( tmp1 ) , evictedMemory ) ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Eviction: %10s / %10s " , tmp0 , tmp1 ) ;
2012-07-24 21:54:19 -07:00
}
# endif // BGFX_CONFIG_RENDERER_OPENGL
2015-08-16 15:37:46 -07:00
pos + + ;
double captureMs = double ( captureElapsed ) * toMs ;
2015-12-03 14:39:26 -08:00
tvm . printf ( 10 , pos + + , 0x8e , " Capture: %7.4f [ms] " , captureMs ) ;
2015-08-16 15:37:46 -07:00
2012-07-08 19:10:07 -07:00
uint8_t attr [ 2 ] = { 0x89 , 0x8a } ;
2014-05-26 14:09:26 -07:00
uint8_t attrIndex = _render - > m_waitSubmit < _render - > m_waitRender ;
2015-08-16 15:37:46 -07:00
tvm . printf ( 10 , pos + + , attr [ attrIndex & 1 ] , " Submit wait: %7.4f [ms] " , double ( _render - > m_waitSubmit ) * toMs ) ;
tvm . printf ( 10 , pos + + , attr [ ( attrIndex + 1 ) & 1 ] , " Render wait: %7.4f [ms] " , double ( _render - > m_waitRender ) * toMs ) ;
2012-08-05 14:51:49 -07:00
min = frameTime ;
max = frameTime ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
blit ( this , _textVideoMemBlitter , tvm ) ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
else if ( _render - > m_debug & BGFX_DEBUG_TEXT )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
blit ( this , _textVideoMemBlitter , _render - > m_textVideoMem ) ;
2012-07-08 19:10:07 -07:00
}
2014-03-29 14:32:16 -07:00
GL_CHECK ( glFrameTerminatorGREMEDY ( ) ) ;
2012-07-08 19:10:07 -07:00
}
2015-03-21 22:11:59 -07:00
} } // namespace bgfx
2014-05-26 14:09:26 -07:00
2015-12-17 17:03:10 +10:00
# undef BGFX_GPU_PROFILER_BIND
# undef BGFX_GPU_PROFILER_UNBIND
# undef BGFX_GPU_PROFILER_BEGIN
# undef BGFX_GPU_PROFILER_BEGIN_DYNAMIC
# undef BGFX_GPU_PROFILER_END
2014-05-26 14:09:26 -07:00
# else
2015-03-21 22:11:59 -07:00
namespace bgfx { namespace gl
2014-05-26 14:09:26 -07:00
{
2015-03-21 22:11:59 -07:00
RendererContextI * rendererCreate ( )
2014-05-26 14:09:26 -07:00
{
return NULL ;
}
2015-03-21 22:11:59 -07:00
void rendererDestroy ( )
2014-05-26 14:09:26 -07:00
{
}
2015-03-21 22:11:59 -07:00
} /* namespace gl */ } // namespace bgfx
2012-07-08 19:10:07 -07:00
2014-08-21 22:05:02 -07:00
# endif // (BGFX_CONFIG_RENDERER_OPENGLES || BGFX_CONFIG_RENDERER_OPENGL)