2012-07-08 19:10:07 -07:00
/*
2014-02-10 22:07:04 -08:00
* Copyright 2011 - 2014 Branimir Karadzic . All rights reserved .
2012-07-08 19:10:07 -07:00
* License : http : //www.opensource.org/licenses/BSD-2-Clause
*/
# 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>
namespace bgfx
{
2013-06-09 15:28:25 -07:00
static char s_viewName [ BGFX_CONFIG_MAX_VIEWS ] [ 256 ] ;
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 } ,
{ GL_POINTS , 1 , 1 , 0 } ,
} ;
static const char * s_primName [ ] =
{
" TriList " ,
" TriStrip " ,
" Line " ,
" 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
{
GL_UNSIGNED_BYTE ,
GL_SHORT ,
GL_HALF_FLOAT ,
GL_FLOAT ,
} ;
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 ,
} ;
static const GLenum s_textureAddress [ ] =
{
GL_REPEAT ,
GL_MIRRORED_REPEAT ,
GL_CLAMP_TO_EDGE ,
} ;
static const GLenum s_textureFilterMag [ ] =
{
GL_LINEAR ,
GL_NEAREST ,
GL_LINEAR ,
} ;
static const GLenum s_textureFilterMin [ ] [ 3 ] =
{
{ GL_LINEAR , GL_LINEAR_MIPMAP_LINEAR , GL_NEAREST_MIPMAP_LINEAR } ,
{ GL_NEAREST , GL_LINEAR_MIPMAP_NEAREST , GL_NEAREST_MIPMAP_NEAREST } ,
{ GL_LINEAR , GL_LINEAR_MIPMAP_LINEAR , GL_NEAREST_MIPMAP_LINEAR } ,
} ;
struct TextureFormatInfo
{
GLenum m_internalFmt ;
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
{
2014-08-26 20:56:53 -07:00
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT , GL_COMPRESSED_RGBA_S3TC_DXT1_EXT , GL_ZERO , false } , // BC1
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT , GL_COMPRESSED_RGBA_S3TC_DXT3_EXT , GL_ZERO , false } , // BC2
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , GL_COMPRESSED_RGBA_S3TC_DXT5_EXT , GL_ZERO , false } , // BC3
{ GL_COMPRESSED_LUMINANCE_LATC1_EXT , GL_COMPRESSED_LUMINANCE_LATC1_EXT , GL_ZERO , false } , // BC4
{ GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT , GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT , GL_ZERO , false } , // BC5
{ GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB , GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB , GL_ZERO , false } , // BC6H
{ GL_COMPRESSED_RGBA_BPTC_UNORM_ARB , GL_COMPRESSED_RGBA_BPTC_UNORM_ARB , GL_ZERO , false } , // BC7
{ GL_ETC1_RGB8_OES , GL_ETC1_RGB8_OES , GL_ZERO , false } , // ETC1
{ GL_COMPRESSED_RGB8_ETC2 , GL_COMPRESSED_RGB8_ETC2 , GL_ZERO , false } , // ETC2
{ GL_COMPRESSED_RGBA8_ETC2_EAC , GL_COMPRESSED_RGBA8_ETC2_EAC , GL_ZERO , false } , // ETC2A
{ GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 , GL_ZERO , false } , // ETC2A1
{ GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG , GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG , GL_ZERO , false } , // PTC12
{ GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG , GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG , GL_ZERO , false } , // PTC14
{ GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG , GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG , GL_ZERO , false } , // PTC12A
{ GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG , GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG , GL_ZERO , false } , // PTC14A
{ GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG , GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG , GL_ZERO , false } , // PTC22
{ GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG , GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG , GL_ZERO , false } , // PTC24
{ GL_ZERO , GL_ZERO , GL_ZERO , true } , // Unknown
{ GL_ZERO , GL_ZERO , GL_ZERO , true } , // R1
{ GL_LUMINANCE , GL_LUMINANCE , GL_UNSIGNED_BYTE , true } , // R8
{ GL_R16 , GL_RED , GL_UNSIGNED_SHORT , true } , // R16
{ GL_R16F , GL_RED , GL_HALF_FLOAT , true } , // R16F
{ GL_R32UI , GL_RED , GL_UNSIGNED_INT , true } , // R32
{ GL_R32F , GL_RED , GL_FLOAT , true } , // R32F
{ GL_RG8 , GL_RG , GL_UNSIGNED_BYTE , true } , // RG8
{ GL_RG16 , GL_RG , GL_UNSIGNED_SHORT , true } , // RG16
{ GL_RG16F , GL_RG , GL_FLOAT , true } , // RG16F
{ GL_RG32UI , GL_RG , GL_UNSIGNED_INT , true } , // RG32
{ GL_RG32F , GL_RG , GL_FLOAT , true } , // RG32F
{ GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE , true } , // BGRA8
{ GL_RGBA16 , GL_RGBA , GL_UNSIGNED_BYTE , true } , // RGBA16
{ GL_RGBA16F , GL_RGBA , GL_HALF_FLOAT , true } , // RGBA16F
{ GL_RGBA32UI , GL_RGBA , GL_UNSIGNED_INT , true } , // RGBA32
{ GL_RGBA32F , GL_RGBA , GL_FLOAT , true } , // RGBA32F
{ GL_RGB565 , GL_RGB , GL_UNSIGNED_SHORT_5_6_5 , true } , // R5G6B5
{ GL_RGBA4 , GL_RGBA , GL_UNSIGNED_SHORT_4_4_4_4 , true } , // RGBA4
{ GL_RGB5_A1 , GL_RGBA , GL_UNSIGNED_SHORT_5_5_5_1 , true } , // RGB5A1
{ GL_RGB10_A2 , GL_RGBA , GL_UNSIGNED_INT_2_10_10_10_REV , true } , // RGB10A2
{ GL_R11F_G11F_B10F , GL_RGB , GL_UNSIGNED_INT_10F_11F_11F_REV , true } , // R11G11B10F
{ GL_ZERO , GL_ZERO , GL_ZERO , true } , // UnknownDepth
{ GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT , GL_UNSIGNED_SHORT , false } , // D16
{ GL_DEPTH_COMPONENT24 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , false } , // D24
{ GL_DEPTH24_STENCIL8 , GL_DEPTH_STENCIL , GL_UNSIGNED_INT_24_8 , false } , // D24S8
{ GL_DEPTH_COMPONENT32 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , false } , // D32
{ GL_DEPTH_COMPONENT32F , GL_DEPTH_COMPONENT , GL_FLOAT , false } , // D16F
{ GL_DEPTH_COMPONENT32F , GL_DEPTH_COMPONENT , GL_FLOAT , false } , // D24F
{ GL_DEPTH_COMPONENT32F , GL_DEPTH_COMPONENT , GL_FLOAT , false } , // D32F
{ GL_STENCIL_INDEX8 , GL_DEPTH_STENCIL , 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 ) ) ;
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
GL_R8 , // R8
GL_R16 , // R16
GL_R16F , // R16F
GL_R32UI , // R32
GL_R32F , // R32F
GL_RG8 , // RG8
GL_RG16 , // RG16
GL_RG16F , // RG16F
GL_RG32UI , // RG32
GL_RG32F , // RG32F
GL_RGBA8 , // BGRA8
GL_RGBA16 , // RGBA16
GL_RGBA16F , // RGBA16F
GL_RGBA32UI , // RGBA32
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 ,
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 ,
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 ,
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 ,
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 ,
2014-02-26 20:24:35 -08:00
ARB_map_buffer_range ,
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 ,
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 ,
2014-09-12 00:02:12 -07:00
EXT_draw_buffers ,
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 ,
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 ,
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 ,
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 ,
2014-03-16 17:43:51 -07:00
MOZ_WEBGL_compressed_texture_s3tc ,
MOZ_WEBGL_depth_texture ,
2014-03-27 22:36:53 -07:00
NV_draw_buffers ,
2013-07-21 19:27:47 -07:00
NVX_gpu_memory_info ,
2014-02-19 23:49:28 -08:00
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 ,
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 ,
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 ,
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 ,
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 ;
} ;
static Extension s_extension [ Extension : : Count ] =
{
2014-08-26 20:56:53 -07:00
{ " AMD_conservative_depth " , false , true } ,
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 } ,
{ " 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 } ,
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 } ,
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 } ,
{ " ARB_map_buffer_range " , BGFX_CONFIG_RENDERER_OPENGL > = 30 , true } ,
{ " 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 } ,
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 } ,
2014-09-12 00:02:12 -07:00
{ " EXT_draw_buffers " , 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 } ,
{ " EXT_occlusion_query_boolean " , false , true } ,
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 } ,
{ " 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.
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 } ,
{ " EXT_timer_query " , false , true } ,
{ " 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 } ,
{ " MOZ_WEBGL_compressed_texture_s3tc " , false , true } ,
{ " MOZ_WEBGL_depth_texture " , false , true } ,
2014-03-27 22:36:53 -07:00
{ " NV_draw_buffers " , false , true } , // GLES2 extension.
2014-03-16 17:43:51 -07:00
{ " NVX_gpu_memory_info " , false , true } ,
{ " OES_compressed_ETC1_RGB8_texture " , false , true } ,
{ " OES_depth24 " , false , true } ,
{ " OES_depth32 " , false , true } ,
{ " OES_depth_texture " , false , true } ,
{ " 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 } ,
{ " OES_vertex_array_object " , false , ! BX_PLATFORM_IOS } ,
{ " OES_vertex_half_float " , false , true } ,
{ " OES_vertex_type_10_10_10_2 " , 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 } ,
{ " 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
} ;
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
} ;
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*/ )
{
}
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
{
2014-03-09 21:20:34 -07:00
# if defined(GL_DEBUG_SOURCE_API_ARB)
2013-04-15 20:59:01 -07:00
switch ( _enum )
{
case GL_DEBUG_SOURCE_API_ARB : return " API " ;
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB : return " WinSys " ;
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB : return " Shader " ;
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB : return " 3rdparty " ;
case GL_DEBUG_SOURCE_APPLICATION_ARB : return " Application " ;
case GL_DEBUG_SOURCE_OTHER_ARB : return " Other " ;
case GL_DEBUG_TYPE_ERROR_ARB : return " Error " ;
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB : return " Deprecated behavior " ;
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB : return " Undefined behavior " ;
case GL_DEBUG_TYPE_PORTABILITY_ARB : return " Portability " ;
case GL_DEBUG_TYPE_PERFORMANCE_ARB : return " Performance " ;
case GL_DEBUG_TYPE_OTHER_ARB : return " Other " ;
case GL_DEBUG_SEVERITY_HIGH_ARB : return " High " ;
case GL_DEBUG_SEVERITY_MEDIUM_ARB : return " Medium " ;
case GL_DEBUG_SEVERITY_LOW_ARB : return " Low " ;
default :
break ;
}
2014-03-09 21:20:34 -07:00
# else
BX_UNUSED ( _enum ) ;
# endif // defined(GL_DEBUG_SOURCE_API_ARB)
2013-04-15 20:59:01 -07:00
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 ;
}
bool isTextureFormatValid ( TextureFormat : : Enum _format )
{
GLuint id ;
GL_CHECK ( glGenTextures ( 1 , & id ) ) ;
GL_CHECK ( glBindTexture ( GL_TEXTURE_2D , id ) ) ;
const TextureFormatInfo & tfi = s_textureFormat [ _format ] ;
2014-04-10 19:21:10 -07:00
GLsizei size = ( 16 * 16 * getBitsPerPixel ( _format ) ) / 8 ;
void * data = alloca ( size ) ;
2014-04-06 21:30:32 -07:00
if ( isCompressed ( _format ) )
2014-04-02 20:52:15 -07:00
{
2014-04-10 19:21:10 -07:00
glCompressedTexImage2D ( GL_TEXTURE_2D , 0 , tfi . m_internalFmt , 16 , 16 , 0 , size , data ) ;
2014-04-02 20:52:15 -07:00
}
2014-04-06 21:30:32 -07:00
else
{
2014-04-10 19:21:10 -07:00
glTexImage2D ( GL_TEXTURE_2D , 0 , tfi . m_internalFmt , 16 , 16 , 0 , tfi . m_fmt , tfi . m_type , data ) ;
2014-04-06 21:30:32 -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 ;
2014-04-02 20:52:15 -07:00
}
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 )
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 )
2013-02-17 20:42:33 -08:00
, m_maxMsaa ( 0 )
2013-03-03 22:30:50 -08:00
, m_vao ( 0 )
2014-02-23 11:21:23 -08:00
, m_vaoSupport ( false )
, m_samplerObjectSupport ( false )
, m_shadowSamplersSupport ( false )
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 )
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-13 21:14:51 -07:00
{
}
~ RendererContextGL ( )
{
}
void init ( )
2012-07-08 19:10:07 -07:00
{
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-05-26 14:09:26 -07:00
m_vendor = getGLString ( GL_VENDOR ) ;
m_renderer = getGLString ( GL_RENDERER ) ;
m_version = getGLString ( GL_VERSION ) ;
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 ) ;
# 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
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
2014-05-26 14:09:26 -07:00
bool supported = false ;
for ( uint32_t ii = 0 ; ii < Extension : : Count ; + + ii )
2014-02-20 23:03:31 -08:00
{
2014-05-26 14:09:26 -07:00
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 ;
}
}
2014-02-20 23:03:31 -08:00
}
2014-02-23 11:21:23 -08:00
2014-05-26 14:09:26 -07:00
BX_TRACE ( " GL_EXTENSION %3d%s: %s " , index , supported ? " (supported) " : " " , name ) ;
BX_UNUSED ( supported ) ;
pos + = len + 1 ;
+ + index ;
}
BX_TRACE ( " Supported extensions: " ) ;
for ( uint32_t ii = 0 ; ii < Extension : : Count ; + + ii )
{
if ( s_extension [ ii ] . m_supported )
2014-02-23 11:21:23 -08:00
{
2014-05-26 14:09:26 -07:00
BX_TRACE ( " \t %2d: %s " , ii , s_extension [ ii ] . m_name ) ;
2014-02-23 11:21:23 -08:00
}
2013-07-24 21:59:59 -07:00
}
2014-02-20 23:03:31 -08:00
}
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 ) ;
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
{
setTextureFormat ( TextureFormat : : R16 , GL_R16UI , GL_RED_INTEGER , GL_UNSIGNED_SHORT ) ;
setTextureFormat ( TextureFormat : : RGBA16 , GL_RGBA16UI , GL_RGBA_INTEGER , GL_UNSIGNED_SHORT ) ;
}
else
{
setTextureFormat ( TextureFormat : : RGBA16F , GL_RGBA , GL_RGBA , GL_HALF_FLOAT ) ;
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
}
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
s_textureFormat [ TextureFormat : : BGRA8 ] . m_fmt = GL_BGRA ;
2014-05-10 20:51:44 -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.
setTextureFormat ( TextureFormat : : BGRA8 , GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE ) ;
}
}
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
if ( ! BX_ENABLED ( BX_PLATFORM_EMSCRIPTEN ) )
{
for ( uint32_t ii = 0 ; ii < TextureFormat : : Count ; + + ii )
2014-05-10 20:51:44 -07:00
{
2014-05-26 14:09:26 -07:00
if ( TextureFormat : : Unknown ! = ii
& & TextureFormat : : UnknownDepth ! = ii )
2014-05-10 20:51:44 -07:00
{
2014-05-26 14:09:26 -07:00
s_textureFormat [ ii ] . m_supported = isTextureFormatValid ( ( TextureFormat : : Enum ) ii ) ;
}
}
}
2014-05-10 20:51:44 -07:00
2014-07-27 20:44:02 -07:00
for ( uint32_t ii = 0 ; ii < TextureFormat : : Count ; + + ii )
{
g_caps . formats [ ii ] = s_textureFormat [ ii ] . m_supported ? 1 : 0 ;
}
2014-05-10 20:51:44 -07:00
2014-05-26 14:09:26 -07:00
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) | | s_extension [ Extension : : OES_texture_3D ] . m_supported
? BGFX_CAPS_TEXTURE_3D
: 0
;
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) | | s_extension [ Extension : : EXT_shadow_samplers ] . m_supported
? BGFX_CAPS_TEXTURE_COMPARE_ALL
: 0
;
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) | | s_extension [ Extension : : OES_vertex_half_float ] . m_supported
? BGFX_CAPS_VERTEX_ATTRIB_HALF
: 0
;
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGL | | BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) | | s_extension [ Extension : : EXT_frag_depth ] . m_supported
? 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
;
2014-05-26 14:09:26 -07:00
g_caps . maxTextureSize = 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 )
| | s_extension [ Extension : : EXT_draw_buffers ] . m_supported )
2014-05-26 14:09:26 -07:00
{
g_caps . maxFBAttachments = bx : : uint32_min ( glGet ( GL_MAX_COLOR_ATTACHMENTS ) , 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 ) )
{
m_vaoSupport & = NULL ! = glGenVertexArrays
& & 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
2014-05-26 14:09:26 -07:00
g_caps . supported | = m_depthTextureSupport
? BGFX_CAPS_TEXTURE_COMPARE_LEQUAL
: 0
;
2014-03-04 22:20:37 -08:00
2014-07-20 20:27:13 -07:00
g_caps . supported | = ! ! ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 )
| | s_extension [ Extension : : ARB_compute_shader ] . m_supported
? BGFX_CAPS_COMPUTE
: 0
;
2014-09-23 20:35:39 -07:00
g_caps . supported | = GlContext : : isSwapChainSupported ( )
? BGFX_CAPS_SWAP_CHAIN
: 0
;
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : EXT_texture_filter_anisotropic ] . m_supported )
{
GL_CHECK ( glGetFloatv ( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT , & m_maxAnisotropy ) ) ;
}
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
{
if ( ! BX_ENABLED ( BX_PLATFORM_IOS ) )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
if ( s_extension [ Extension : : ARB_instanced_arrays ] . m_supported
| | s_extension [ Extension : : ANGLE_instanced_arrays ] . m_supported )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
if ( NULL ! = glVertexAttribDivisor
& & NULL ! = glDrawArraysInstanced
& & NULL ! = glDrawElementsInstanced )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07: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 ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL > = 31 )
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 30 ) )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
s_textureFormat [ TextureFormat : : R8 ] . m_internalFmt = GL_R8 ;
s_textureFormat [ TextureFormat : : R8 ] . m_fmt = GL_RED ;
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
# if BGFX_CONFIG_RENDERER_OPENGL
if ( s_extension [ Extension : : ARB_debug_output ] . m_supported
| | s_extension [ Extension : : KHR_debug ] . m_supported )
{
GL_CHECK ( glDebugMessageCallback ( debugProcCb , NULL ) ) ;
GL_CHECK ( glDebugMessageControl ( GL_DONT_CARE , GL_DONT_CARE , GL_DEBUG_SEVERITY_MEDIUM_ARB , 0 , NULL , GL_TRUE ) ) ;
}
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 ( s_extension [ Extension : : ARB_depth_clamp ] . m_supported )
{
GL_CHECK ( glEnable ( GL_DEPTH_CLAMP ) ) ;
}
# endif // BGFX_CONFIG_RENDERER_OPENGL
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
2014-05-26 14:09:26 -07:00
if ( NULL = = glObjectLabel )
{
glObjectLabel = stubObjectLabel ;
}
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
{
m_queries . create ( ) ;
}
}
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
{
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 ( ) ;
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
m_queries . destroy ( ) ;
2014-03-04 22:20:37 -08:00
}
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-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 ;
}
void flip ( )
{
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-05-26 14:09:26 -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
2014-05-26 14:09:26 -07:00
void createIndexBuffer ( IndexBufferHandle _handle , Memory * _mem ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . create ( _mem - > size , _mem - > data ) ;
}
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
{
}
void createVertexBuffer ( VertexBufferHandle _handle , Memory * _mem , VertexDeclHandle _declHandle ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . create ( _mem - > size , _mem - > data , _declHandle ) ;
}
void destroyVertexBuffer ( VertexBufferHandle _handle ) BX_OVERRIDE
{
m_vertexBuffers [ _handle . idx ] . destroy ( ) ;
}
void createDynamicIndexBuffer ( IndexBufferHandle _handle , uint32_t _size ) BX_OVERRIDE
{
m_indexBuffers [ _handle . idx ] . create ( _size , NULL ) ;
}
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 ( ) ;
}
void createDynamicVertexBuffer ( VertexBufferHandle _handle , uint32_t _size ) BX_OVERRIDE
{
VertexDeclHandle decl = BGFX_INVALID_HANDLE ;
m_vertexBuffers [ _handle . idx ] . create ( _size , NULL , decl ) ;
}
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
{
}
void destroyTexture ( TextureHandle _handle ) BX_OVERRIDE
{
m_textures [ _handle . idx ] . destroy ( ) ;
}
void createFrameBuffer ( FrameBufferHandle _handle , uint8_t _num , const TextureHandle * _textureHandles ) BX_OVERRIDE
{
m_frameBuffers [ _handle . idx ] . create ( _num , _textureHandles ) ;
}
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-05-26 14:09:26 -07:00
uint32_t width = m_resolution . m_width ;
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
2014-05-26 14:09:26 -07:00
void updateViewName ( uint8_t _id , const char * _name ) BX_OVERRIDE
{
bx : : strlcpy ( & s_viewName [ _id ] [ 0 ] , _name , BX_COUNTOF ( s_viewName [ 0 ] ) ) ;
}
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-05-26 14:09:26 -07:00
uint32_t width = m_resolution . m_width ;
uint32_t height = m_resolution . m_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 ] ;
mtxOrtho ( proj , 0.0f , ( float ) width , ( float ) height , 0.0f , 0.0f , 1000.0f ) ;
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 ) ) ;
}
void blitRender ( TextVideoMemBlitter & _blitter , uint32_t _numIndices ) BX_OVERRIDE
{
uint32_t numVertices = _numIndices * 4 / 6 ;
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 ) ;
VertexBufferGL & vb = m_vertexBuffers [ _blitter . m_vb - > handle . idx ] ;
GL_CHECK ( glBindBuffer ( GL_ARRAY_BUFFER , vb . m_id ) ) ;
IndexBufferGL & ib = m_indexBuffers [ _blitter . m_ib - > handle . idx ] ;
GL_CHECK ( glBindBuffer ( GL_ELEMENT_ARRAY_BUFFER , ib . m_id ) ) ;
ProgramGL & program = m_program [ _blitter . m_program . idx ] ;
program . bindAttributes ( _blitter . m_decl , 0 ) ;
GL_CHECK ( glDrawElements ( GL_TRIANGLES
, _numIndices
, GL_UNSIGNED_SHORT
, ( void * ) 0
) ) ;
}
void updateResolution ( const Resolution & _resolution )
{
if ( m_resolution . m_width ! = _resolution . m_width
2014-06-22 18:51:14 -07:00
| | m_resolution . m_height ! = _resolution . m_height
| | m_resolution . m_flags ! = _resolution . m_flags )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
m_textVideoMem . resize ( false , _resolution . m_width , _resolution . m_height ) ;
m_textVideoMem . clear ( ) ;
m_resolution = _resolution ;
uint32_t msaa = ( m_resolution . m_flags & BGFX_RESET_MSAA_MASK ) > > BGFX_RESET_MSAA_SHIFT ;
msaa = bx : : uint32_min ( m_maxMsaa , msaa = = 0 ? 0 : 1 < < msaa ) ;
bool vsync = ! ! ( m_resolution . m_flags & BGFX_RESET_VSYNC ) ;
setRenderContextSize ( _resolution . m_width , _resolution . m_height , msaa , vsync ) ;
updateCapture ( ) ;
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
uint32_t setFrameBuffer ( FrameBufferHandle _fbh , uint32_t _height , bool _msaa = true )
{
if ( isValid ( m_fbh )
2014-06-22 18:51:14 -07:00
& & m_fbh . idx ! = _fbh . idx
& & m_rtMsaa )
2014-05-26 14:09:26 -07:00
{
FrameBufferGL & frameBuffer = m_frameBuffers [ m_fbh . idx ] ;
frameBuffer . resolve ( ) ;
}
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 ) ) ;
}
else
{
FrameBufferGL & frameBuffer = m_frameBuffers [ _fbh . idx ] ;
2014-09-24 19:22:15 -07:00
_height = frameBuffer . m_height ;
2014-09-07 17:17:38 -07:00
if ( UINT16_MAX ! = frameBuffer . m_denseIdx )
{
m_glctx . makeCurrent ( frameBuffer . m_swapChain ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ) ;
}
else
{
m_glctx . makeCurrent ( NULL ) ;
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , frameBuffer . m_fbo [ 0 ] ) ) ;
}
2014-03-04 22:20:37 -08:00
}
2014-05-26 14:09:26 -07:00
m_fbh = _fbh ;
m_rtMsaa = _msaa ;
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
2014-05-26 14:09:26 -07: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
: 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 ) ) ;
GL_CHECK ( glDeleteRenderbuffers ( BX_COUNTOF ( m_msaaBackBufferRbos ) , m_msaaBackBufferRbos ) ) ;
m_msaaBackBufferFbo = 0 ;
}
}
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 ) ) ;
uint32_t width = m_resolution . m_width ;
uint32_t height = m_resolution . m_height ;
GLenum filter = BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) | | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES < 30 )
? GL_NEAREST
: 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
}
void setRenderContextSize ( uint32_t _width , uint32_t _height , uint32_t _msaa = 0 , bool _vsync = false )
{
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 ( ) ;
m_glctx . resize ( _width , _height , _vsync ) ;
2014-03-04 22:20:37 -08:00
2014-05-26 14:09:26 -07:00
createMsaaFbo ( _width , _height , _msaa ) ;
}
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
}
void setSamplerState ( uint32_t _stage , uint32_t _numMips , uint32_t _flags )
{
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
{
2014-05-26 14:09:26 -07:00
if ( 0 = = ( BGFX_SAMPLER_DEFAULT_FLAGS & _flags ) )
2014-03-04 22:20:37 -08:00
{
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 ;
GLuint sampler = m_samplerStateCache . find ( _flags ) ;
if ( UINT32_MAX = = sampler )
2014-03-04 22:20:37 -08:00
{
2014-05-26 14:09:26 -07:00
sampler = m_samplerStateCache . add ( _flags ) ;
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 ] ) ) ;
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 ;
GLenum minFilter = s_textureFilterMin [ min ] [ 1 < _numMips ? mip + 1 : 0 ] ;
GL_CHECK ( glSamplerParameteri ( sampler , GL_TEXTURE_MAG_FILTER , s_textureFilterMag [ mag ] ) ) ;
GL_CHECK ( glSamplerParameteri ( sampler , GL_TEXTURE_MIN_FILTER , minFilter ) ) ;
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
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
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
2014-05-26 14:09:26 -07:00
void commit ( ConstantBuffer & _constantBuffer )
{
_constantBuffer . reset ( ) ;
2014-06-08 20:57:39 -07:00
for ( ; ; )
2014-02-20 23:03:31 -08:00
{
2014-05-26 14:09:26 -07:00
uint32_t opcode = _constantBuffer . read ( ) ;
if ( UniformType : : End = = opcode )
{
break ;
}
UniformType : : Enum type ;
uint16_t ignore ;
uint16_t num ;
uint16_t copy ;
ConstantBuffer : : decodeOpcode ( opcode , type , ignore , num , copy ) ;
const char * data ;
if ( copy )
{
data = _constantBuffer . read ( g_uniformTypeSize [ type ] * num ) ;
}
else
{
UniformHandle handle ;
memcpy ( & handle , _constantBuffer . read ( sizeof ( UniformHandle ) ) , sizeof ( UniformHandle ) ) ;
data = ( const char * ) m_uniforms [ handle . idx ] ;
}
uint32_t loc = _constantBuffer . read ( ) ;
# 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 )
{
// case ConstantType::Uniform1iv:
// {
// int* value = (int*)data;
// BX_TRACE("Uniform1iv sampler %d, loc %d (num %d, copy %d)", *value, loc, num, copy);
// GL_CHECK(glUniform1iv(loc, num, value) );
// }
// break;
CASE_IMPLEMENT_UNIFORM ( Uniform1i , 1 iv , I , int ) ;
CASE_IMPLEMENT_UNIFORM ( Uniform1f , 1f v , F , float ) ;
CASE_IMPLEMENT_UNIFORM ( Uniform1iv , 1 iv , I , int ) ;
CASE_IMPLEMENT_UNIFORM ( Uniform1fv , 1f v , F , float ) ;
CASE_IMPLEMENT_UNIFORM ( Uniform2fv , 2f v , F , float ) ;
CASE_IMPLEMENT_UNIFORM ( Uniform3fv , 3f v , F , float ) ;
CASE_IMPLEMENT_UNIFORM ( Uniform4fv , 4f v , F , float ) ;
CASE_IMPLEMENT_UNIFORM_T ( Uniform3x3fv , Matrix3fv , F , float ) ;
CASE_IMPLEMENT_UNIFORM_T ( Uniform4x4fv , Matrix4fv , F , float ) ;
case UniformType : : End :
break ;
default :
BX_TRACE ( " %4d: INVALID 0x%08x, t %d, l %d, n %d, c %d " , _constantBuffer . getPos ( ) , opcode , type , loc , num , copy ) ;
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 ;
if ( BGFX_CLEAR_COLOR_BIT & _clear . m_flags )
{
if ( BGFX_CLEAR_COLOR_USE_PALETTE_BIT & _clear . m_flags )
{
uint8_t index = ( uint8_t ) bx : : uint32_min ( BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE - 1 , _clear . m_index [ 0 ] ) ;
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 ) ) ;
}
if ( BGFX_CLEAR_DEPTH_BIT & _clear . m_flags )
{
flags | = GL_DEPTH_BUFFER_BIT ;
GL_CHECK ( glClearDepth ( _clear . m_depth ) ) ;
GL_CHECK ( glDepthMask ( GL_TRUE ) ) ;
}
if ( BGFX_CLEAR_STENCIL_BIT & _clear . m_flags )
{
flags | = GL_STENCIL_BUFFER_BIT ;
GL_CHECK ( glClearStencil ( _clear . m_stencil ) ) ;
}
if ( 0 ! = flags )
{
GL_CHECK ( glEnable ( GL_SCISSOR_TEST ) ) ;
GL_CHECK ( glScissor ( _rect . m_x , _height - _rect . m_height - _rect . m_y , _rect . m_width , _rect . m_height ) ) ;
GL_CHECK ( glClear ( flags ) ) ;
GL_CHECK ( glDisable ( GL_SCISSOR_TEST ) ) ;
}
}
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 ) ) ;
GLboolean colorMask = ! ! ( BGFX_CLEAR_COLOR_BIT & _clear . m_flags ) ;
GL_CHECK ( glColorMask ( colorMask , colorMask , colorMask , colorMask ) ) ;
if ( BGFX_CLEAR_DEPTH_BIT & _clear . m_flags )
{
GL_CHECK ( glEnable ( GL_DEPTH_TEST ) ) ;
GL_CHECK ( glDepthFunc ( GL_ALWAYS ) ) ;
GL_CHECK ( glDepthMask ( GL_TRUE ) ) ;
}
else
{
GL_CHECK ( glDisable ( GL_DEPTH_TEST ) ) ;
}
if ( BGFX_CLEAR_STENCIL_BIT & _clear . m_flags )
{
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
} ;
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 ) ) ;
const float depth = _clear . m_depth ;
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
2014-09-01 11:24:51 -07:00
if ( BGFX_CLEAR_COLOR_USE_PALETTE_BIT & _clear . m_flags )
2014-05-26 14:09:26 -07:00
{
2014-09-01 11:24:51 -07:00
float mrtClear [ BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ] [ 4 ] ;
for ( uint32_t ii = 0 ; ii < numMrt ; + + ii )
{
uint8_t index = ( uint8_t ) bx : : uint32_min ( BGFX_CONFIG_MAX_CLEAR_COLOR_PALETTE - 1 , _clear . m_index [ ii ] ) ;
memcpy ( mrtClear [ ii ] , _palette [ index ] , 16 ) ;
}
2012-07-08 19:10:07 -07:00
2014-09-01 11:24:51 -07:00
GL_CHECK ( glUniform4fv ( 0 , numMrt , mrtClear [ 0 ] ) ) ;
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 ] =
{
_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 ,
} ;
GL_CHECK ( glUniform4fv ( 0 , 1 , rgba ) ) ;
2014-05-26 14:09:26 -07:00
}
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-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 ] ;
2014-05-26 14:09:26 -07:00
QueriesGL m_queries ;
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 ;
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 ;
2013-02-17 20:42:33 -08:00
int32_t m_maxMsaa ;
2013-03-03 22:30:50 -08:00
GLuint m_vao ;
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 ;
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 ;
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 ;
2012-07-08 19:10:07 -07:00
} ;
2014-05-26 14:09:26 -07:00
RendererContextGL * s_renderGL ;
RendererContextI * rendererCreateGL ( )
{
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 ;
}
void rendererDestroyGL ( )
{
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 ) ;
GLSL_TYPE ( GL_INT_VEC4 ) ;
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 ) ;
// GLSL_TYPE(GL_FLOAT_MAT2x3);
// GLSL_TYPE(GL_FLOAT_MAT2x4);
// GLSL_TYPE(GL_FLOAT_MAT3x2);
// GLSL_TYPE(GL_FLOAT_MAT3x4);
// GLSL_TYPE(GL_FLOAT_MAT4x2);
// GLSL_TYPE(GL_FLOAT_MAT4x3);
// GLSL_TYPE(GL_SAMPLER_1D);
GLSL_TYPE ( GL_SAMPLER_2D ) ;
2012-11-25 18:24:50 -08:00
GLSL_TYPE ( GL_SAMPLER_3D ) ;
2012-07-08 19:10:07 -07:00
GLSL_TYPE ( GL_SAMPLER_CUBE ) ;
// GLSL_TYPE(GL_SAMPLER_1D_SHADOW);
2014-02-23 11:21:23 -08:00
GLSL_TYPE ( GL_SAMPLER_2D_SHADOW ) ;
2014-07-20 20:27:13 -07:00
GLSL_TYPE ( GL_IMAGE_1D ) ;
GLSL_TYPE ( GL_IMAGE_2D ) ;
GLSL_TYPE ( GL_IMAGE_3D ) ;
GLSL_TYPE ( GL_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 ) ;
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 :
2014-04-26 23:48:41 -07:00
return UniformType : : Uniform1iv ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT :
2012-10-27 21:34:41 -07:00
return UniformType : : Uniform1fv ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT_VEC2 :
2012-10-27 21:34:41 -07:00
return UniformType : : Uniform2fv ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT_VEC3 :
2012-10-27 21:34:41 -07:00
return UniformType : : Uniform3fv ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT_VEC4 :
2012-10-27 21:34:41 -07:00
return UniformType : : Uniform4fv ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT_MAT2 :
break ;
case GL_FLOAT_MAT3 :
2012-10-27 21:34:41 -07:00
return UniformType : : Uniform3x3fv ;
2012-07-08 19:10:07 -07:00
case GL_FLOAT_MAT4 :
2012-10-27 21:34:41 -07:00
return UniformType : : Uniform4x4fv ;
2012-07-08 19:10:07 -07:00
// case GL_FLOAT_MAT2x3:
// case GL_FLOAT_MAT2x4:
// case GL_FLOAT_MAT3x2:
// case GL_FLOAT_MAT3x4:
// case GL_FLOAT_MAT4x2:
// case GL_FLOAT_MAT4x3:
// break;
2012-11-25 18:24:50 -08:00
// case GL_SAMPLER_1D:
2012-07-08 19:10:07 -07:00
case GL_SAMPLER_2D :
2012-11-25 18:24:50 -08:00
case GL_SAMPLER_3D :
2012-07-08 19:10:07 -07:00
case GL_SAMPLER_CUBE :
// case GL_SAMPLER_1D_SHADOW:
2014-02-23 11:21:23 -08:00
case GL_SAMPLER_2D_SHADOW :
2014-07-20 20:27:13 -07:00
case GL_IMAGE_1D :
case GL_IMAGE_2D :
case GL_IMAGE_3D :
case GL_IMAGE_CUBE :
2012-10-27 21:34:41 -07:00
return UniformType : : Uniform1iv ;
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 ( ) ;
2012-09-16 17:36:08 -07:00
BX_TRACE ( " program create: %d: %d, %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 )
{
GL_CHECK ( glAttachShader ( m_id , _vsh . m_id ) ) ;
2014-07-20 20:27:13 -07:00
if ( 0 ! = _fsh . m_id )
{
GL_CHECK ( glAttachShader ( m_id , _fsh . m_id ) ) ;
}
2012-07-08 19:10:07 -07:00
GL_CHECK ( glLinkProgram ( m_id ) ) ;
GLint linked = 0 ;
GL_CHECK ( glGetProgramiv ( m_id , GL_LINK_STATUS , & linked ) ) ;
if ( 0 = = linked )
{
char log [ 1024 ] ;
GL_CHECK ( glGetProgramInfoLog ( m_id , sizeof ( log ) , NULL , log ) ) ;
BX_TRACE ( " %d: %s " , linked , log ) ;
GL_CHECK ( glDeleteProgram ( m_id ) ) ;
return ;
}
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 )
{
ConstantBuffer : : destroy ( m_constantBuffer ) ;
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
2014-07-20 20:27:13 -07:00
if ( s_extension [ Extension : : ARB_program_interface_query ] . m_supported
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 ) )
{
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 ;
2014-07-24 21:30:57 -07:00
struct VariableInfo
{
GLenum type ;
GLint loc ;
GLint num ;
} ;
VariableInfo vi ;
GLenum props [ ] = { GL_TYPE , GL_LOCATION , GL_ARRAY_SIZE } ;
const bool piqSupported = s_extension [ Extension : : ARB_program_interface_query ] . m_supported ;
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 )
{
GLenum gltype ;
2014-07-24 21:30:57 -07:00
GLint num ;
GLint loc ;
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 )
| | piqSupported )
{
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 , ' ] ' ) ;
* end = ' \0 ' ;
offset = atoi ( array ) ;
}
2014-02-23 11:21:23 -08:00
switch ( gltype )
{
case GL_SAMPLER_2D :
case GL_SAMPLER_3D :
case GL_SAMPLER_CUBE :
case GL_SAMPLER_2D_SHADOW :
2014-07-20 20:27:13 -07:00
case GL_IMAGE_1D :
case GL_IMAGE_2D :
case GL_IMAGE_3D :
case GL_IMAGE_CUBE :
BX_TRACE ( " Sampler #%d at location %d. " , m_numSamplers , loc ) ;
2014-02-23 11:21:23 -08:00
m_sampler [ m_numSamplers ] = loc ;
m_numSamplers + + ;
break ;
default :
break ;
}
2012-07-08 19:10:07 -07:00
PredefinedUniform : : Enum predefined = nameToPredefinedUniformEnum ( name ) ;
if ( PredefinedUniform : : Count ! = predefined )
{
m_predefined [ m_numPredefined ] . m_loc = loc ;
m_predefined [ m_numPredefined ] . m_type = predefined ;
m_predefined [ m_numPredefined ] . m_count = num ;
m_numPredefined + + ;
}
else
{
2014-05-26 14:09:26 -07:00
const UniformInfo * info = s_renderGL - > m_uniformReg . find ( name ) ;
2012-07-08 19:10:07 -07:00
if ( NULL ! = info )
{
2014-10-08 19:36:59 -07:00
if ( NULL = = m_constantBuffer )
{
m_constantBuffer = ConstantBuffer : : create ( 1024 ) ;
}
2012-10-27 21:34:41 -07:00
UniformType : : Enum type = convertGlType ( gltype ) ;
2014-04-15 19:10:56 -07:00
m_constantBuffer - > writeUniformHandle ( type , 0 , info - > m_handle , 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 ( ) ;
}
2014-07-20 20:27:13 -07:00
if ( s_extension [ Extension : : ARB_program_interface_query ] . m_supported
| | BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGLES > = 31 ) )
{
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 ;
for ( uint32_t ii = 0 ; ii < Attrib : : Count ; + + ii )
{
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 ;
}
}
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 ;
}
}
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
{
2013-10-23 21:18:01 -07:00
if ( 0xff ! = _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 ] ;
GL_CHECK ( glVertexAttribPointer ( loc , num , s_attribType [ type ] , normalized , _vertexDecl . m_stride , ( void * ) ( uintptr_t ) baseVertex ) ) ;
}
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 ) ) ;
}
}
2014-05-26 14:09:26 -07:00
bool TextureGL : : init ( GLenum _target , uint32_t _width , uint32_t _height , uint8_t _format , uint8_t _numMips , uint32_t _flags )
2013-04-15 20:59:01 -07:00
{
m_target = _target ;
2013-07-24 21:59:59 -07:00
m_numMips = _numMips ;
m_flags = _flags ;
m_currentFlags = UINT32_MAX ;
2014-02-05 23:07:11 -08:00
m_width = _width ;
m_height = _height ;
2013-09-08 21:03:03 -07:00
m_requestedFormat = _format ;
m_textureFormat = _format ;
2013-04-15 20:59:01 -07:00
2014-02-05 23:07:11 -08:00
const bool bufferOnly = 0 ! = ( m_flags & BGFX_TEXTURE_RT_BUFFER_ONLY ) ;
2013-04-15 20:59:01 -07:00
2014-02-05 23:07:11 -08:00
if ( ! bufferOnly )
{
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
2014-02-05 23:07:11 -08:00
setSamplerState ( _flags ) ;
2013-09-08 21:03:03 -07:00
2014-02-05 23:07:11 -08:00
const TextureFormatInfo & tfi = s_textureFormat [ _format ] ;
2013-09-08 21:03:03 -07:00
m_fmt = tfi . m_fmt ;
m_type = tfi . m_type ;
2014-02-05 23:07:11 -08:00
2014-02-20 22:05:50 -08:00
const bool compressed = isCompressed ( TextureFormat : : Enum ( _format ) ) ;
2014-02-05 23:07:11 -08:00
const bool decompress = ! tfi . m_supported & & compressed ;
if ( decompress )
{
m_textureFormat = ( uint8_t ) TextureFormat : : BGRA8 ;
const TextureFormatInfo & tfi = s_textureFormat [ TextureFormat : : BGRA8 ] ;
m_fmt = tfi . m_fmt ;
m_type = tfi . m_type ;
}
2013-09-08 21:03:03 -07:00
2014-03-31 22:41:56 -07:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
& & TextureFormat : : BGRA8 = = m_textureFormat
2014-03-25 23:07:51 -07:00
& & GL_RGBA = = m_fmt
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
| | bufferOnly )
{
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
, s_textureFormat [ m_textureFormat ] . m_internalFmt
, _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
, s_textureFormat [ m_textureFormat ] . m_internalFmt
, _width
, _height
) ) ;
}
GL_CHECK ( glBindRenderbuffer ( GL_RENDERBUFFER , 0 ) ) ;
if ( bufferOnly )
{
// 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 ;
2014-02-19 22:34:53 -08:00
const uint32_t startLod = bx : : uint32_min ( _skip , numMips - 1 ) ;
2014-07-24 21:30:57 -07:00
numMips - = uint8_t ( startLod ) ;
2014-03-01 19:27:34 -08:00
const ImageBlockInfo & blockInfo = getBlockInfo ( TextureFormat : : Enum ( imageContainer . m_format ) ) ;
const uint32_t textureWidth = bx : : uint32_max ( blockInfo . blockWidth , imageContainer . m_width > > startLod ) ;
const uint32_t textureHeight = bx : : uint32_max ( blockInfo . blockHeight , imageContainer . m_height > > startLod ) ;
2012-07-08 19:10:07 -07:00
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
2014-02-05 23:07:11 -08:00
, imageContainer . m_format
, numMips
, _flags
) )
{
return ;
}
2012-07-08 19:10:07 -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
2013-09-08 21:03:03 -07:00
const GLenum internalFmt = 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
& & TextureFormat : : BGRA8 = = m_textureFormat
& & GL_RGBA = = m_fmt
2014-05-26 14:09:26 -07:00
& & ! s_renderGL - > m_textureSwizzleSupport
2014-02-16 10:50:58 -08:00
;
2013-09-08 21:03:03 -07:00
const bool convert = m_textureFormat ! = m_requestedFormat ;
2014-02-20 22:05:50 -08:00
const bool compressed = isCompressed ( TextureFormat : : Enum ( m_textureFormat ) ) ;
2014-03-01 20:08:50 -08:00
uint32_t blockWidth = 1 ;
uint32_t blockHeight = 1 ;
if ( convert & & compressed )
{
blockWidth = blockInfo . blockWidth ;
blockHeight = blockInfo . blockHeight ;
}
2013-01-14 20:10:07 -08:00
2014-04-19 15:02:43 -07:00
BX_TRACE ( " Texture %3d: %s (requested: %s), %dx%d%s%s. "
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
, imageContainer . m_cubeMap ? " x6 " : " "
, 0 ! = ( m_flags & BGFX_TEXTURE_RT_MASK ) ? " (render target) " : " "
) ;
2014-02-14 20:43:00 -08:00
BX_WARN ( ! swizzle & & ! convert , " Texture %s%s%s from %s to %s. "
, 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 ;
if ( convert | | swizzle )
{
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
2013-09-08 21:03:03 -07:00
for ( uint32_t lod = 0 , num = numMips ; lod < num ; + + lod )
2012-07-08 19:10:07 -07:00
{
2014-03-01 20:08:50 -08:00
width = bx : : uint32_max ( blockWidth , width ) ;
height = bx : : uint32_max ( blockHeight , 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
{
2013-09-08 21:03:03 -07:00
if ( compressed )
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 )
{
2013-11-07 22:59:17 -08:00
imageDecodeToBgra8 ( 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
if ( swizzle )
{
2013-11-07 22:59:17 -08:00
imageSwizzleBgra8 ( width , height , mip . m_width * 4 , data , temp ) ;
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
}
}
2013-09-08 21:03:03 -07:00
else
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
{
if ( 0 ! = m_id )
{
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
}
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
& & TextureFormat : : BGRA8 = = m_textureFormat
& & GL_RGBA = = m_fmt
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 ) ;
2013-11-08 20:53:23 -08:00
const bool convert = m_textureFormat ! = m_requestedFormat ;
2014-02-20 22:05:50 -08:00
const bool compressed = isCompressed ( TextureFormat : : Enum ( m_textureFormat ) ) ;
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
| | swizzle
| | ! 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
{
2013-11-07 22:59:17 -08:00
imageDecodeToBgra8 ( temp , data , width , height , srcpitch , 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
if ( swizzle )
2012-08-19 18:50:23 -07:00
{
2013-11-07 22:59:17 -08:00
imageSwizzleBgra8 ( width , height , srcpitch , data , temp ) ;
2013-09-08 21:03:03 -07:00
data = temp ;
2012-08-19 18:50:23 -07:00
}
2013-11-08 20:53:23 -08:00
else if ( ! unpackRowLength & & ! convert )
{
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
) ) ;
}
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
}
2014-05-26 14:09:26 -07:00
void TextureGL : : setSamplerState ( uint32_t _flags )
2013-07-24 21:59:59 -07:00
{
2014-04-09 21:23:27 -07:00
const uint32_t flags = ( 0 ! = ( BGFX_SAMPLER_DEFAULT_FLAGS & _flags ) ? m_flags : _flags ) & BGFX_TEXTURE_SAMPLER_BITS_MASK ;
if ( flags ! = m_currentFlags )
2013-07-24 21:59:59 -07:00
{
const GLenum target = m_target ;
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 ] ) ) ;
}
2014-02-23 11:21:23 -08:00
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 ;
const GLenum minFilter = s_textureFilterMin [ min ] [ 1 < numMips ? mip + 1 : 0 ] ;
2013-07-24 21:59:59 -07:00
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_MAG_FILTER , s_textureFilterMag [ mag ] ) ) ;
GL_CHECK ( glTexParameteri ( target , GL_TEXTURE_MIN_FILTER , minFilter ) ) ;
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 ] ) ) ;
}
}
2013-07-24 21:59:59 -07:00
m_currentFlags = flags ;
}
}
2014-05-26 14:09:26 -07:00
void TextureGL : : commit ( uint32_t _stage , uint32_t _flags )
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.
setSamplerState ( _flags ) ;
}
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
{
2014-05-26 14:09:26 -07:00
s_renderGL - > setSamplerState ( _stage , m_numMips , _flags ) ;
2014-02-20 23:03:31 -08:00
}
else
{
setSamplerState ( _flags ) ;
}
2013-07-24 21:59:59 -07:00
}
else
{
2014-02-20 23:03:31 -08:00
// Everything else has sampler object.
2014-05-26 14:09:26 -07:00
s_renderGL - > setSamplerState ( _stage , m_numMips , _flags ) ;
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 )
{
uint8_t nameSize ;
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 ) ;
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 "
) ;
2014-05-10 20:51:44 -07:00
bool usesDerivatives = s_extension [ Extension : : OES_standard_derivatives ] . m_supported
& & 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 )
{
BX_WARN ( s_extension [ Extension : : EXT_draw_buffers ] . m_supported , " EXT_draw_buffers is used but not supported by GLES2 driver. " ) ;
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. " ) ;
if ( s_extension [ Extension : : EXT_shader_texture_lod ] . m_supported )
{
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 " ) ;
}
}
2014-05-10 20:51:44 -07:00
writeString ( & writer , " precision mediump float; \n " ) ;
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
{
2014-05-10 20:51:44 -07:00
bool usesTextureLod = s_extension [ Extension : : ARB_shader_texture_lod ] . m_supported
& & bx : : findIdentifierMatch ( code , s_ARB_shader_texture_lod )
;
2014-04-19 18:16:26 -07:00
2014-05-10 20:51:44 -07:00
if ( usesTextureLod )
2014-02-09 16:46:50 -08:00
{
2014-05-10 20:51:44 -07:00
writeString ( & writer , " #version 120 \n " ) ;
2014-02-13 22:50:52 -08:00
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
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
}
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 texture2DLod textureLod \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 texture3DLod textureLod \n " ) ;
writeString ( & writer , " #define textureCube texture \n " ) ;
writeString ( & writer , " #define textureCubeLod textureLod \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 )
{
char temp [ 16 ] ;
bx : : snprintf ( temp , BX_COUNTOF ( temp ) , " gl_FragData[%d] " , ii ) ;
fragData = bx : : uint32_max ( fragData , NULL = = strstr ( code , temp ) ? 0 : ii + 1 ) ;
}
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 ) ) ;
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 ) ;
}
2014-05-26 14:09:26 -07:00
void FrameBufferGL : : create ( uint8_t _num , const TextureHandle * _handles )
2012-07-08 19:10:07 -07:00
{
2014-02-05 23:07:11 -08:00
GL_CHECK ( glGenFramebuffers ( 1 , & m_fbo [ 0 ] ) ) ;
2014-02-24 21:44:12 -08:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_fbo [ 0 ] ) ) ;
2013-02-17 20:42:33 -08:00
2014-09-07 17:17:38 -07:00
// m_denseIdx = UINT16_MAX;
2014-02-05 23:07:11 -08:00
bool needResolve = false ;
2014-01-08 22:08:37 -08:00
2014-03-27 21:35:14 -07:00
GLenum buffers [ BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS ] ;
2014-02-24 22:00:26 -08:00
uint32_t colorIdx = 0 ;
for ( uint32_t ii = 0 ; ii < _num ; + + ii )
2013-02-17 20:42:33 -08:00
{
2014-02-05 23:07:11 -08:00
TextureHandle handle = _handles [ ii ] ;
if ( isValid ( handle ) )
2012-07-08 19:10:07 -07:00
{
2014-05-26 14:09:26 -07:00
const TextureGL & texture = s_renderGL - > m_textures [ handle . idx ] ;
2013-02-18 21:17:29 -08:00
2014-02-24 22:10:19 -08:00
if ( 0 = = colorIdx )
{
m_width = texture . m_width ;
m_height = texture . m_height ;
}
2014-02-05 23:07:11 -08:00
GLenum attachment = GL_COLOR_ATTACHMENT0 + colorIdx ;
if ( isDepth ( ( TextureFormat : : Enum ) texture . m_textureFormat ) )
2013-02-18 21:17:29 -08:00
{
2014-02-05 23:07:11 -08:00
attachment = GL_DEPTH_ATTACHMENT ;
2013-02-18 21:17:29 -08:00
}
else
{
2014-03-27 21:35:14 -07:00
buffers [ colorIdx ] = attachment ;
2014-02-05 23:07:11 -08:00
+ + colorIdx ;
2013-02-18 21:17:29 -08:00
}
2012-07-08 19:10:07 -07:00
2014-02-05 23:07:11 -08:00
if ( 0 ! = texture . m_rbo )
2013-12-29 11:43:44 -08:00
{
2014-02-24 21:44:12 -08:00
GL_CHECK ( glFramebufferRenderbuffer ( GL_FRAMEBUFFER
2014-02-05 23:07:11 -08:00
, attachment
2013-12-29 11:43:44 -08:00
, GL_RENDERBUFFER
2014-02-05 23:07:11 -08:00
, texture . m_rbo
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
{
2014-02-24 21:44:12 -08:00
GL_CHECK ( glFramebufferTexture2D ( GL_FRAMEBUFFER
2014-02-05 23:07:11 -08:00
, attachment
, texture . m_target
, texture . m_id
, 0
2013-12-29 11:43:44 -08:00
) ) ;
}
2014-02-05 23:07:11 -08:00
needResolve | = ( 0 ! = texture . m_rbo ) & & ( 0 ! = texture . m_id ) ;
2012-07-08 19:10:07 -07:00
}
2014-02-05 23:07:11 -08:00
}
2014-03-25 23:07:51 -07:00
m_num = colorIdx ;
2014-02-24 22:02:43 -08:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL ) )
2014-02-24 22:00:26 -08:00
{
if ( 0 = = colorIdx )
{
// When only depth is attached disable draw buffer to avoid
// GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER.
2014-02-25 22:20:09 -08:00
GL_CHECK ( glDrawBuffer ( GL_NONE ) ) ;
2014-02-24 22:00:26 -08:00
}
2014-03-27 21:35:14 -07:00
else
{
GL_CHECK ( glDrawBuffers ( colorIdx , buffers ) ) ;
}
2014-02-24 22:00:26 -08:00
// Disable read buffer to avoid GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER.
2014-02-25 22:20:09 -08:00
GL_CHECK ( glReadBuffer ( GL_NONE ) ) ;
2014-02-24 22:00:26 -08:00
}
2014-04-01 22:31:02 -07:00
frameBufferValidate ( ) ;
2014-02-05 23:07:11 -08:00
if ( needResolve )
{
GL_CHECK ( glGenFramebuffers ( 1 , & m_fbo [ 1 ] ) ) ;
2014-02-24 21:44:12 -08:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , m_fbo [ 1 ] ) ) ;
2014-02-05 23:07:11 -08:00
for ( uint32_t ii = 0 , colorIdx = 0 ; ii < _num ; + + ii )
2012-07-08 19:10:07 -07:00
{
2014-02-05 23:07:11 -08:00
TextureHandle handle = _handles [ ii ] ;
if ( isValid ( handle ) )
{
2014-05-26 14:09:26 -07:00
const TextureGL & texture = s_renderGL - > m_textures [ handle . idx ] ;
2014-02-05 23:07:11 -08:00
if ( 0 ! = texture . m_id )
{
GLenum attachment = GL_COLOR_ATTACHMENT0 + colorIdx ;
2014-03-25 23:07:51 -07:00
if ( ! isDepth ( ( TextureFormat : : Enum ) texture . m_textureFormat ) )
2014-02-05 23:07:11 -08:00
{
+ + colorIdx ;
2014-02-24 21:44:12 -08:00
GL_CHECK ( glFramebufferTexture2D ( GL_FRAMEBUFFER
2014-02-05 23:07:11 -08:00
, attachment
, texture . m_target
, texture . m_id
, 0
) ) ;
}
}
}
2012-07-08 19:10:07 -07:00
}
2014-04-01 22:31:02 -07:00
frameBufferValidate ( ) ;
2013-02-18 21:17:29 -08:00
}
2012-07-08 19:10:07 -07:00
2014-05-26 14:09:26 -07:00
GL_CHECK ( glBindFramebuffer ( GL_FRAMEBUFFER , s_renderGL - > m_msaaBackBufferFbo ) ) ;
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 ) ) ;
memset ( m_fbo , 0 , sizeof ( m_fbo ) ) ;
m_num = 0 ;
}
2014-09-07 17:17:38 -07:00
if ( NULL ! = m_swapChain )
{
s_renderGL - > m_glctx . destorySwapChain ( m_swapChain ) ;
m_swapChain = NULL ;
}
uint16_t denseIdx = m_denseIdx ;
m_denseIdx = UINT16_MAX ;
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
}
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
{
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 ;
2014-02-20 23:03:31 -08:00
if ( BX_ENABLED ( BGFX_CONFIG_RENDERER_OPENGL )
2014-05-26 14:09:26 -07:00
& & ( _render - > m_debug & ( BGFX_DEBUG_IFH | BGFX_DEBUG_STATS ) ) )
2012-07-08 19:10:07 -07:00
{
2014-09-24 19:22:15 -07:00
m_queries . begin ( 0 , GL_TIME_ELAPSED ) ;
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 ;
2014-09-24 19:22:15 -07:00
m_indexBuffers [ ib - > handle . idx ] . update ( 0 , _render - > m_iboffset , ib - > data ) ;
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 ;
2014-09-24 19:22:15 -07:00
m_vertexBuffers [ vb - > handle . idx ] . update ( 0 , _render - > m_vboffset , vb - > data ) ;
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 ( ) ;
2012-07-08 19:10:07 -07:00
currentState . m_flags = BGFX_STATE_NONE ;
2012-11-10 19:59:23 -08:00
currentState . m_stencil = packStencil ( BGFX_STENCIL_NONE , BGFX_STENCIL_NONE ) ;
2012-07-08 19:10:07 -07:00
Matrix4 viewProj [ BGFX_CONFIG_MAX_VIEWS ] ;
for ( uint32_t ii = 0 ; ii < BGFX_CONFIG_MAX_VIEWS ; + + ii )
{
2014-05-26 14:09:26 -07:00
bx : : float4x4_mul ( & viewProj [ ii ] . un . f4x4 , & _render - > m_view [ ii ] . un . f4x4 , & _render - > m_proj [ ii ] . un . f4x4 ) ;
2012-07-08 19:10:07 -07:00
}
2014-05-10 20:51:44 -07:00
Matrix4 invView ;
Matrix4 invProj ;
Matrix4 invViewProj ;
uint8_t invViewCached = 0xff ;
uint8_t invProjCached = 0xff ;
uint8_t invViewProjCached = 0xff ;
2012-09-16 17:36:08 -07:00
uint16_t programIdx = invalidHandle ;
2012-07-08 19:10:07 -07:00
SortKey key ;
uint8_t view = 0xff ;
2014-02-05 23:07:11 -08:00
FrameBufferHandle fbh = BGFX_INVALID_HANDLE ;
2014-05-26 14:09:26 -07:00
int32_t height = _render - > m_resolution . m_height ;
2012-07-08 19:10:07 -07:00
float alphaRef = 0.0f ;
2013-03-29 22:58:50 -07:00
uint32_t blendFactor = 0 ;
2014-04-26 23:48:41 -07:00
2014-05-26 14:09:26 -07:00
const uint64_t pt = _render - > m_debug & BGFX_DEBUG_WIREFRAME ? BGFX_STATE_PT_LINES : 0 ;
2014-04-26 23:48:41 -07:00
uint8_t primIndex = uint8_t ( pt > > BGFX_STATE_PT_SHIFT ) ;
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 ;
2013-08-01 22:55:26 -07:00
bool viewHasScissor = false ;
Rect viewScissorRect ;
2013-08-04 16:56:07 -07:00
viewScissorRect . clear ( ) ;
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 ;
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-05-26 14:09:26 -07:00
for ( uint32_t item = 0 , numItems = _render - > m_num ; item < numItems ; + + item )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
const bool isCompute = key . decode ( _render - > m_sortKeys [ item ] ) ;
const bool viewChanged = key . m_view ! = view ;
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 ] ] ;
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-03-29 14:32:16 -07:00
GL_CHECK ( glInsertEventMarker ( 0 , s_viewName [ key . m_view ] ) ) ;
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 ] ;
2014-09-24 19:22:15 -07:00
height = setFrameBuffer ( fbh , _render - > m_resolution . m_height ) ;
2012-07-08 19:10:07 -07:00
}
2014-05-26 14:09:26 -07:00
const Rect & rect = _render - > m_rect [ view ] ;
const Rect & scissorRect = _render - > m_scissor [ view ] ;
2013-08-01 22:55:26 -07:00
viewHasScissor = ! scissorRect . isZero ( ) ;
viewScissorRect = viewHasScissor ? scissorRect : rect ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glViewport ( rect . m_x , height - rect . m_height - rect . m_y , rect . m_width , rect . m_height ) ) ;
2014-05-26 14:09:26 -07:00
Clear & clear = _render - > m_clear [ view ] ;
2012-07-08 19:10:07 -07:00
if ( BGFX_CLEAR_NONE ! = clear . m_flags )
{
2014-09-01 11:24:51 -07:00
clearQuad ( _clearQuad , rect , clear , height , _render - > m_clearColor ) ;
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 ) ) ;
}
2014-07-20 20:27:13 -07:00
if ( isCompute )
{
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 )
{
const ComputeBinding & bind = compute . m_bind [ ii ] ;
if ( invalidHandle ! = bind . m_idx )
{
switch ( bind . m_type )
{
case ComputeBinding : : Image :
{
const TextureGL & texture = m_textures [ bind . m_idx ] ;
GL_CHECK ( glBindImageTexture ( ii , texture . m_id , bind . m_mip , GL_FALSE , 0 , s_access [ bind . m_access ] , s_imageFormat [ bind . m_format ] ) ) ;
barrier | = GL_SHADER_IMAGE_ACCESS_BARRIER_BIT ;
}
break ;
case ComputeBinding : : Buffer :
{
// const VertexBufferGL& vertexBuffer = m_vertexBuffers[bind.m_idx];
// GL_CHECK(glBindBufferBase(GL_SHADER_STORAGE_BUFFER, ii, vertexBuffer.m_id) );
// barrier |= GL_SHADER_STORAGE_BARRIER_BIT;
}
break ;
}
}
}
if ( 0 ! = barrier )
{
bool constantsChanged = compute . m_constBegin < compute . m_constEnd ;
rendererUpdateUniforms ( this , _render - > m_constantBuffer , compute . m_constBegin , compute . m_constEnd ) ;
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 ) ;
}
GL_CHECK ( glDispatchCompute ( compute . m_numX , compute . m_numY , compute . m_numZ ) ) ;
GL_CHECK ( glMemoryBarrier ( barrier ) ) ;
}
}
continue ;
}
const RenderDraw & draw = renderItem . draw ;
const uint64_t newFlags = draw . m_flags ;
uint64_t changedFlags = currentState . m_flags ^ draw . m_flags ;
currentState . m_flags = newFlags ;
const uint64_t newStencil = draw . m_stencil ;
uint64_t changedStencil = currentState . m_stencil ^ draw . m_stencil ;
currentState . m_stencil = newStencil ;
if ( viewChanged )
{
currentState . clear ( ) ;
currentState . m_scissor = ! draw . m_scissor ;
changedFlags = BGFX_STATE_MASK ;
changedStencil = packStencil ( BGFX_STENCIL_MASK , BGFX_STENCIL_MASK ) ;
currentState . m_flags = newFlags ;
currentState . m_stencil = newStencil ;
}
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 ) ) ;
2013-08-01 22:55:26 -07:00
GL_CHECK ( glScissor ( viewScissorRect . m_x , height - viewScissorRect . m_height - viewScissorRect . m_y , 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 ) ) ;
GL_CHECK ( glScissor ( scissorRect . m_x , height - scissorRect . m_height - scissorRect . m_y , scissorRect . m_width , scissorRect . m_height ) ) ;
}
}
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 ) ;
uint32_t frontAndBack = bstencil ! = BGFX_STENCIL_NONE & & bstencil ! = unpackStencil ( 0 , newStencil ) ;
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
for ( uint32_t ii = 0 , num = frontAndBack + 1 ; ii < num ; + + ii )
{
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 ;
2014-02-23 11:21:23 -08: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
) & 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 ;
alphaRef = ref / 255.0f ;
}
# 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 )
{
if ( BGFX_STATE_MSAA & newFlags )
{
GL_CHECK ( glEnable ( GL_MULTISAMPLE ) ) ;
}
else
{
GL_CHECK ( glDisable ( GL_MULTISAMPLE ) ) ;
}
}
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 ) ) ;
}
2014-03-25 23:07:51 -07:00
if ( ( BGFX_STATE_BLEND_MASK | BGFX_STATE_BLEND_EQUATION_MASK | BGFX_STATE_BLEND_INDEPENDENT ) & changedFlags
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
if ( ( 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
const uint32_t blend = uint32_t ( ( newFlags & BGFX_STATE_BLEND_MASK ) > > BGFX_STATE_BLEND_SHIFT ) ;
const uint32_t equation = uint32_t ( ( newFlags & BGFX_STATE_BLEND_EQUATION_MASK ) > > BGFX_STATE_BLEND_EQUATION_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
2014-03-25 23:07:51 -07:00
const uint32_t equRGB = ( equation ) & 0x7 ;
const uint32_t equA = ( equation > > 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 ;
2014-07-20 20:27:13 -07:00
rendererUpdateUniforms ( this , _render - > m_constantBuffer , 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 ;
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
}
2012-09-16 17:36:08 -07:00
for ( uint32_t ii = 0 , num = program . m_numPredefined ; ii < num ; + + ii )
2012-07-08 19:10:07 -07:00
{
2012-09-16 17:36:08 -07:00
PredefinedUniform & predefined = program . m_predefined [ ii ] ;
2012-07-08 19:10:07 -07:00
switch ( predefined . m_type )
{
case PredefinedUniform : : ViewRect :
{
float rect [ 4 ] ;
2014-05-26 14:09:26 -07:00
rect [ 0 ] = _render - > m_rect [ view ] . m_x ;
rect [ 1 ] = _render - > m_rect [ view ] . m_y ;
rect [ 2 ] = _render - > m_rect [ view ] . m_width ;
rect [ 3 ] = _render - > m_rect [ view ] . m_height ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glUniform4fv ( predefined . m_loc
, 1
, & rect [ 0 ]
) ) ;
}
break ;
case PredefinedUniform : : ViewTexel :
{
float rect [ 4 ] ;
2014-05-26 14:09:26 -07:00
rect [ 0 ] = 1.0f / float ( _render - > m_rect [ view ] . m_width ) ;
rect [ 1 ] = 1.0f / float ( _render - > m_rect [ view ] . m_height ) ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glUniform4fv ( predefined . m_loc
, 1
, & rect [ 0 ]
) ) ;
}
break ;
case PredefinedUniform : : View :
{
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
2014-05-26 14:09:26 -07:00
, _render - > m_view [ view ] . un . val
2012-07-08 19:10:07 -07:00
) ) ;
}
break ;
2014-05-10 20:51:44 -07:00
case PredefinedUniform : : InvView :
{
if ( view ! = invViewCached )
{
invViewCached = view ;
2014-05-26 14:09:26 -07:00
bx : : float4x4_inverse ( & invView . un . f4x4 , & _render - > m_view [ view ] . un . f4x4 ) ;
2014-05-10 20:51:44 -07:00
}
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
, invView . un . val
) ) ;
}
break ;
case PredefinedUniform : : Proj :
{
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
2014-05-26 14:09:26 -07:00
, _render - > m_proj [ view ] . un . val
2014-05-10 20:51:44 -07:00
) ) ;
}
break ;
case PredefinedUniform : : InvProj :
{
if ( view ! = invProjCached )
{
invProjCached = view ;
2014-05-26 14:09:26 -07:00
bx : : float4x4_inverse ( & invProj . un . f4x4 , & _render - > m_proj [ view ] . un . f4x4 ) ;
2014-05-10 20:51:44 -07:00
}
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
, invProj . un . val
) ) ;
}
break ;
2012-07-08 19:10:07 -07:00
case PredefinedUniform : : ViewProj :
{
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
2014-01-18 23:33:00 -08:00
, viewProj [ view ] . un . val
2012-07-08 19:10:07 -07:00
) ) ;
}
break ;
2014-05-10 20:51:44 -07:00
case PredefinedUniform : : InvViewProj :
{
if ( view ! = invViewProjCached )
{
invViewProjCached = view ;
bx : : float4x4_inverse ( & invViewProj . un . f4x4 , & viewProj [ view ] . un . f4x4 ) ;
}
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
, invViewProj . un . val
) ) ;
}
break ;
2012-07-08 19:10:07 -07:00
case PredefinedUniform : : Model :
{
2014-07-20 20:27:13 -07:00
const Matrix4 & model = _render - > m_matrixCache . m_cache [ draw . m_matrix ] ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
2014-07-20 20:27:13 -07:00
, bx : : uint32_min ( predefined . m_count , draw . m_num )
2012-07-08 19:10:07 -07:00
, GL_FALSE
2014-01-18 23:33:00 -08:00
, model . un . val
2012-07-08 19:10:07 -07:00
) ) ;
}
break ;
2012-10-07 20:41:18 -07:00
case PredefinedUniform : : ModelView :
{
Matrix4 modelView ;
2014-07-20 20:27:13 -07:00
const Matrix4 & model = _render - > m_matrixCache . m_cache [ draw . m_matrix ] ;
2014-05-26 14:09:26 -07:00
bx : : float4x4_mul ( & modelView . un . f4x4 , & model . un . f4x4 , & _render - > m_view [ view ] . un . f4x4 ) ;
2012-10-07 20:41:18 -07:00
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
2014-01-18 23:33:00 -08:00
, modelView . un . val
2012-10-07 20:41:18 -07:00
) ) ;
}
break ;
2012-07-08 19:10:07 -07:00
case PredefinedUniform : : ModelViewProj :
{
Matrix4 modelViewProj ;
2014-07-20 20:27:13 -07:00
const Matrix4 & model = _render - > m_matrixCache . m_cache [ draw . m_matrix ] ;
2014-01-18 23:33:00 -08:00
bx : : float4x4_mul ( & modelViewProj . un . f4x4 , & model . un . f4x4 , & viewProj [ view ] . un . f4x4 ) ;
2012-07-08 19:10:07 -07:00
GL_CHECK ( glUniformMatrix4fv ( predefined . m_loc
, 1
, GL_FALSE
2014-01-18 23:33:00 -08:00
, modelViewProj . un . val
2012-07-08 19:10:07 -07:00
) ) ;
}
break ;
case PredefinedUniform : : AlphaRef :
{
GL_CHECK ( glUniform1f ( predefined . m_loc , alphaRef ) ) ;
}
break ;
case PredefinedUniform : : Count :
break ;
}
}
{
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
{
2014-07-20 20:27:13 -07:00
const Sampler & sampler = draw . m_sampler [ stage ] ;
2012-07-08 19:10:07 -07:00
Sampler & current = currentState . m_sampler [ stage ] ;
if ( current . m_idx ! = sampler . m_idx
| | current . m_flags ! = sampler . m_flags
2012-09-16 17:36:08 -07:00
| | programChanged )
2012-07-08 19:10:07 -07:00
{
2012-07-29 13:50:23 -07:00
if ( invalidHandle ! = sampler . m_idx )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
TextureGL & texture = m_textures [ sampler . m_idx ] ;
2014-02-10 21:06:46 -08:00
texture . commit ( stage , sampler . m_flags ) ;
2012-07-08 19:10:07 -07:00
}
}
current = sampler ;
}
}
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
2014-07-20 20:27:13 -07:00
| | currentState . m_vertexBuffer . idx ! = draw . m_vertexBuffer . idx
| | currentState . m_indexBuffer . idx ! = draw . m_indexBuffer . 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
{
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 ) ;
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 ) ) ;
2014-07-20 20:27:13 -07:00
ProgramGL & program = m_program [ programIdx ] ;
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 ;
const ProgramGL & program = m_program [ programIdx ] ;
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 ;
}
2012-07-08 19:10:07 -07:00
uint32_t numIndices = 0 ;
uint32_t numPrimsSubmitted = 0 ;
uint32_t numInstances = 0 ;
uint32_t numPrimsRendered = 0 ;
2014-07-20 20:27:13 -07:00
if ( isValid ( draw . m_indexBuffer ) )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
if ( UINT32_MAX = = draw . m_numIndices )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
numIndices = m_indexBuffers [ draw . m_indexBuffer . idx ] . m_size / 2 ;
2014-04-26 23:48:41 -07:00
numPrimsSubmitted = numIndices / prim . m_div - prim . m_sub ;
2014-07-20 20:27:13 -07:00
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
2012-07-08 19:10:07 -07:00
2014-04-26 23:48:41 -07:00
GL_CHECK ( glDrawElementsInstanced ( prim . m_type
2012-08-09 22:06:22 -07:00
, numIndices
2012-07-08 19:10:07 -07:00
, GL_UNSIGNED_SHORT
, ( void * ) 0
2014-07-20 20:27:13 -07:00
, draw . m_numInstances
2012-07-08 19:10:07 -07:00
) ) ;
}
2014-07-20 20:27:13 -07:00
else if ( prim . m_min < = draw . m_numIndices )
2012-07-08 19:10:07 -07:00
{
2014-07-20 20:27:13 -07:00
numIndices = draw . m_numIndices ;
2014-04-26 23:48:41 -07:00
numPrimsSubmitted = numIndices / prim . m_div - prim . m_sub ;
2014-07-20 20:27:13 -07:00
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
2012-07-08 19:10:07 -07:00
2014-04-26 23:48:41 -07:00
GL_CHECK ( glDrawElementsInstanced ( prim . m_type
2012-07-08 19:10:07 -07:00
, numIndices
, GL_UNSIGNED_SHORT
2014-07-20 20:27:13 -07:00
, ( void * ) ( uintptr_t ) ( draw . m_startIndex * 2 )
, draw . m_numInstances
2012-07-08 19:10:07 -07:00
) ) ;
}
}
else
{
2014-04-26 23:48:41 -07:00
numPrimsSubmitted = numVertices / prim . m_div - prim . m_sub ;
2014-07-20 20:27:13 -07:00
numInstances = draw . m_numInstances ;
numPrimsRendered = numPrimsSubmitted * draw . m_numInstances ;
2012-07-08 19:10:07 -07:00
2014-04-26 23:48:41 -07:00
GL_CHECK ( glDrawArraysInstanced ( prim . m_type
2012-07-08 19:10:07 -07:00
, 0
2012-11-03 13:12:26 -07:00
, numVertices
2014-07-20 20:27:13 -07:00
, draw . m_numInstances
2012-07-08 19:10:07 -07:00
) ) ;
}
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
2014-05-26 14:09:26 -07:00
if ( 0 < _render - > m_num )
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 ( ) ;
}
2012-07-08 19:10:07 -07:00
}
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 ;
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 ;
2014-05-26 14:09:26 -07:00
if ( _render - > m_debug & ( BGFX_DEBUG_IFH | BGFX_DEBUG_STATS ) )
2012-07-08 19:10:07 -07:00
{
double elapsedGpuMs = 0.0 ;
# if BGFX_CONFIG_RENDERER_OPENGL
2014-07-20 20:27:13 -07:00
m_queries . end ( GL_TIME_ELAPSED ) ;
uint64_t elapsedGl = m_queries . getResult ( 0 ) ;
2012-07-08 19:10:07 -07:00
elapsedGpuMs = double ( elapsedGl ) / 1e6 ;
# endif // BGFX_CONFIG_RENDERER_OPENGL
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 )
{
next = now + bx : : getHPFrequency ( ) ;
double freq = double ( bx : : getHPFrequency ( ) ) ;
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 ( )
) ;
2014-07-20 20:27:13 -07:00
tvm . printf ( 0 , pos + + , 0x0f , " Vendor: %s " , m_vendor ) ;
tvm . printf ( 0 , pos + + , 0x0f , " Renderer: %s " , m_renderer ) ;
tvm . printf ( 0 , pos + + , 0x0f , " Version: %s " , m_version ) ;
tvm . printf ( 0 , pos + + , 0x0f , " GLSL version: %s " , m_glslVersion ) ;
2013-04-20 23:13:44 -07:00
pos = 10 ;
2014-02-05 23:07:11 -08:00
tvm . printf ( 10 , pos + + , 0x8e , " Frame CPU: %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
) ;
const uint32_t msaa = ( m_resolution . m_flags & BGFX_RESET_MSAA_MASK ) > > BGFX_RESET_MSAA_SHIFT ;
tvm . printf ( 10 , pos + + , 0x8e , " Reset flags: [%c] vsync, [%c] MSAAx%d "
, ! ! ( m_resolution . m_flags & BGFX_RESET_VSYNC ) ? ' \xfe ' : ' '
, 0 ! = msaa ? ' \xfe ' : ' '
, 1 < < msaa
2012-08-05 14:51:49 -07:00
) ;
2012-12-30 20:52:47 -08:00
double elapsedCpuMs = double ( elapsed ) * toMs ;
2012-07-08 19:10:07 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Draw calls: %4d / CPU %3.4f [ms] %c GPU %3.4f [ms] "
2014-05-26 14:09:26 -07:00
, _render - > m_num
2012-07-08 19:10:07 -07:00
, elapsedCpuMs
, elapsedCpuMs > elapsedGpuMs ? ' > ' : ' < '
, elapsedGpuMs
) ;
2014-04-26 23:48:41 -07:00
for ( uint32_t ii = 0 ; ii < BX_COUNTOF ( s_primInfo ) ; + + ii )
{
tvm . printf ( 10 , pos + + , 0x8e , " %8s: %7d (#inst: %5d), submitted: %7d "
, s_primName [ ii ]
, statsNumPrimsRendered [ ii ]
, statsNumInstances [ ii ]
, statsNumPrimsSubmitted [ ii ]
) ;
}
2012-12-30 20:52:47 -08:00
2012-07-08 19:10:07 -07:00
tvm . printf ( 10 , pos + + , 0x8e , " Indices: %7d " , statsNumIndices ) ;
2014-05-26 14:09:26 -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 ( )
) ;
pos + + ;
2014-04-26 23:48:41 -07:00
double captureMs = double ( captureElapsed ) * toMs ;
tvm . printf ( 10 , pos + + , 0x8e , " Capture: %3.4f [ms] " , captureMs ) ;
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 + + ;
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 ] ) ;
tvm . printf ( 10 , pos + + , 0x8e , " VBO: %10s, %10s, %10s, %10s " , tmp0 , tmp1 , tmp2 , tmp3 ) ;
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 ] ) ;
tvm . printf ( 10 , pos + + , 0x8e , " Texture: %10s, %10s, %10s, %10s " , tmp0 , tmp1 , tmp2 , tmp3 ) ;
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 ] ) ;
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 ) ) ;
2014-08-25 20:50:36 -07:00
pos + = 2 ;
char tmp0 [ 16 ] ;
char tmp1 [ 16 ] ;
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , dedicated ) ;
tvm . printf ( 10 , pos + + , 0x8e , " Dedicated: %10s " , tmp0 ) ;
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , currAvail ) ;
bx : : prettify ( tmp1 , BX_COUNTOF ( tmp1 ) , totalAvail ) ;
tvm . printf ( 10 , pos + + , 0x8e , " Available: %10s / %10s " , tmp0 , tmp1 ) ;
bx : : prettify ( tmp0 , BX_COUNTOF ( tmp0 ) , evictedCount ) ;
bx : : prettify ( tmp1 , BX_COUNTOF ( tmp1 ) , evictedMemory ) ;
tvm . printf ( 10 , pos + + , 0x8e , " Eviction: %10s / %10s " , tmp0 , tmp1 ) ;
2012-07-24 21:54:19 -07:00
}
# endif // BGFX_CONFIG_RENDERER_OPENGL
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 ;
2012-07-08 19:10:07 -07:00
2012-07-24 21:54:19 -07:00
pos + + ;
2014-05-26 14:09:26 -07:00
tvm . printf ( 10 , pos + + , attr [ attrIndex & 1 ] , " Submit wait: %3.4f [ms] " , double ( _render - > m_waitSubmit ) * toMs ) ;
tvm . printf ( 10 , pos + + , attr [ ( attrIndex + 1 ) & 1 ] , " Render wait: %3.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
}
2014-05-26 14:09:26 -07:00
} // namespace bgfx
# else
namespace bgfx
{
RendererContextI * rendererCreateGL ( )
{
return NULL ;
}
void rendererDestroyGL ( )
{
}
} // 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)