void FOpenGLES2::ProcessExtensions( const FString& ExtensionsString ) { ProcessQueryGLInt(); FOpenGLBase::ProcessExtensions(ExtensionsString); bSupportsMapBuffer = ExtensionsString.Contains(TEXT("GL_OES_mapbuffer")); bSupportsDepthTexture = ExtensionsString.Contains(TEXT("GL_OES_depth_texture")); bSupportsOcclusionQueries = ExtensionsString.Contains(TEXT("GL_ARB_occlusion_query2")) || ExtensionsString.Contains(TEXT("GL_EXT_occlusion_query_boolean")); bSupportsDisjointTimeQueries = ExtensionsString.Contains(TEXT("GL_EXT_disjoint_timer_query")) || ExtensionsString.Contains(TEXT("GL_NV_timer_query")); bTimerQueryCanBeDisjoint = !ExtensionsString.Contains(TEXT("GL_NV_timer_query")); bSupportsRGBA8 = ExtensionsString.Contains(TEXT("GL_OES_rgb8_rgba8")); bSupportsBGRA8888 = ExtensionsString.Contains(TEXT("GL_APPLE_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_IMG_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_format_BGRA8888")); bSupportsVertexHalfFloat = ExtensionsString.Contains(TEXT("GL_OES_vertex_half_float")); bSupportsTextureFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_float")); bSupportsTextureHalfFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_half_float")); bSupportsSGRB = ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsColorBufferHalfFloat = ExtensionsString.Contains(TEXT("GL_EXT_color_buffer_half_float")); bSupportsShaderFramebufferFetch = ExtensionsString.Contains(TEXT("GL_EXT_shader_framebuffer_fetch")) || ExtensionsString.Contains(TEXT("GL_NV_shader_framebuffer_fetch")); bSupportsMultisampledRenderToTexture = ExtensionsString.Contains(TEXT("GL_EXT_multisampled_render_to_texture")); // @todo ios7: SRGB support does not work with our texture format setup (ES2 docs indicate that internalFormat and format must match, but they don't at all with sRGB enabled) // One possible solution us to use GLFormat.InternalFormat[bSRGB] instead of GLFormat.Format bSupportsSGRB = false;//ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsDXT = ExtensionsString.Contains(TEXT("GL_NV_texture_compression_s3tc")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_compression_s3tc")); bSupportsPVRTC = ExtensionsString.Contains(TEXT("GL_IMG_texture_compression_pvrtc")) ; bSupportsATITC = ExtensionsString.Contains(TEXT("GL_ATI_texture_compression_atitc")) || ExtensionsString.Contains(TEXT("GL_AMD_compressed_ATC_texture")); bSupportsETC1 = ExtensionsString.Contains(TEXT("GL_OES_compressed_ETC1_RGB8_texture")); bSupportsVertexArrayObjects = ExtensionsString.Contains(TEXT("GL_OES_vertex_array_object")) ; bSupportsDiscardFrameBuffer = ExtensionsString.Contains(TEXT("GL_EXT_discard_framebuffer")); bSupportsNVFrameBufferBlit = ExtensionsString.Contains(TEXT("GL_NV_framebuffer_blit")); bSupportsPackedDepthStencil = ExtensionsString.Contains(TEXT("GL_OES_packed_depth_stencil")); bSupportsShaderTextureLod = ExtensionsString.Contains(TEXT("GL_EXT_shader_texture_lod")); bSupportsTextureStorageEXT = ExtensionsString.Contains(TEXT("GL_EXT_texture_storage")); bSupportsCopyTextureLevels = bSupportsTextureStorageEXT && ExtensionsString.Contains(TEXT("GL_APPLE_copy_texture_levels")); bSupportsTextureNPOT = ExtensionsString.Contains(TEXT("GL_OES_texture_npot")) || ExtensionsString.Contains(TEXT("GL_ARB_texture_non_power_of_two")); bSupportsStandardDerivativesExtension = ExtensionsString.Contains(TEXT("GL_OES_standard_derivatives")); if (!bSupportsStandardDerivativesExtension) { UE_LOG(LogRHI, Warning, TEXT("GL_OES_standard_derivatives not supported. There may be rendering errors if materials depend on dFdx, dFdy, or fwidth.")); } // Report shader precision int Range[2]; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_FLOAT, Range, &ShaderLowPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, Range, &ShaderMediumPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, Range, &ShaderHighPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader lowp precision: %d"), ShaderLowPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader mediump precision: %d"), ShaderMediumPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader highp precision: %d"), ShaderHighPrecision); if ( FPlatformMisc::IsDebuggerPresent() && UE_BUILD_DEBUG ) { // Enable GL debug markers if we're running in Xcode extern int32 GEmitMeshDrawEvent; GEmitMeshDrawEvent = 1; GEmitDrawEvents = true; } // ES2 requires a color attachment when rendering to depth-only. GSupportsDepthRenderTargetWithoutColorRenderTarget = false; }
bool OsmAnd::GPUAPI_OpenGLES2::isShaderPrecisionFormatSupported(GLenum shaderType, GLenum precisionType) { GL_CHECK_PRESENT(glGetShaderPrecisionFormat); GLint range[] = { 0, 0 }; GLint precision = 0; glGetShaderPrecisionFormat(shaderType, precisionType, range, &precision); GL_CHECK_RESULT; if (range[0] == 0 && range[1] == 0) return false; return true; }
//------------------------------------------------------- ChilliSource::RenderInfo RenderInfoFactory::CreateRenderInfo() noexcept { bool areHighPrecFragmentsSupported = true; bool areMapBuffersSupported = true; bool areVAOsSupported = true; bool areDepthTexturesSupported = false; bool areShadowMapsSupported = false; u32 maxTextureSize = 0; u32 maxTextureUnits = 0; u32 maxVertexAttribs = 0; #ifdef CS_OPENGLVERSION_ES s32 fragmentHighRanges[2]; s32 fragmentHighPrecision; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, fragmentHighRanges, &fragmentHighPrecision); areHighPrecFragmentsSupported = fragmentHighPrecision != 0 && fragmentHighRanges[0] != 0 && fragmentHighRanges[1] != 0; #ifdef CS_TARGETPLATFORM_ANDROID //Check for map buffer support areMapBuffersSupported = CheckForOpenGLExtension("GL_OES_mapbuffer"); areVAOsSupported = CheckForOpenGLExtension("GL_OES_vertex_array_object"); #endif #ifdef CS_TARGETPLATFORM_RPI areVAOsSupported = false; #endif #endif #ifdef CS_OPENGLVERSION_STANDARD areDepthTexturesSupported = CheckForOpenGLExtension("GL_ARB_depth_texture"); #elif defined(CS_OPENGLVERSION_ES) areDepthTexturesSupported = CheckForOpenGLExtension("GL_OES_depth_texture"); #endif areShadowMapsSupported = (areDepthTexturesSupported && areHighPrecFragmentsSupported); glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&maxTextureSize); glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, (GLint*)&maxTextureUnits); glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, (GLint*)&maxVertexAttribs); CS_ASSERT_NOGLERROR("An OpenGL error occurred while getting render capabilities."); ChilliSource::RenderInfo renderInfo(areShadowMapsSupported, areDepthTexturesSupported, areMapBuffersSupported, areVAOsSupported, areHighPrecFragmentsSupported, maxTextureSize, maxTextureUnits, maxVertexAttribs); return renderInfo; }
void FHTML5OpenGL::ProcessExtensions( const FString& ExtensionsString ) { FOpenGLES2::ProcessQueryGLInt(); FOpenGLBase::ProcessExtensions(ExtensionsString); bSupportsMapBuffer = ExtensionsString.Contains(TEXT("GL_OES_mapbuffer")); bSupportsDepthTexture = ExtensionsString.Contains(TEXT("GL_OES_depth_texture")); bSupportsOcclusionQueries = ExtensionsString.Contains(TEXT("GL_ARB_occlusion_query2")) || ExtensionsString.Contains(TEXT("GL_EXT_occlusion_query_boolean")); bSupportsRGBA8 = ExtensionsString.Contains(TEXT("GL_OES_rgb8_rgba8")); bSupportsBGRA8888 = ExtensionsString.Contains(TEXT("GL_APPLE_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_IMG_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_format_BGRA8888")); bSupportsVertexHalfFloat = false;//ExtensionsString.Contains(TEXT("GL_OES_vertex_half_float")); bSupportsTextureFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_float")); bSupportsTextureHalfFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_half_float")); bSupportsSGRB = ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsColorBufferHalfFloat = ExtensionsString.Contains(TEXT("GL_EXT_color_buffer_half_float")); bSupportsShaderFramebufferFetch = ExtensionsString.Contains(TEXT("GL_EXT_shader_framebuffer_fetch")) || ExtensionsString.Contains(TEXT("GL_NV_shader_framebuffer_fetch")); // @todo ios7: SRGB support does not work with our texture format setup (ES2 docs indicate that internalFormat and format must match, but they don't at all with sRGB enabled) // One possible solution us to use GLFormat.InternalFormat[bSRGB] instead of GLFormat.Format bSupportsSGRB = false;//ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsDXT = ExtensionsString.Contains(TEXT("GL_NV_texture_compression_s3tc")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_compression_s3tc")) || ExtensionsString.Contains(TEXT("WEBGL_compressed_texture_s3tc")) || (ExtensionsString.Contains(TEXT("GL_EXT_texture_compression_dxt1")) && // ANGLE (for HTML5_Win32) exposes these 3 as discrete extensions ExtensionsString.Contains(TEXT("GL_ANGLE_texture_compression_dxt3")) && ExtensionsString.Contains(TEXT("GL_ANGLE_texture_compression_dxt5")) ); bSupportsPVRTC = ExtensionsString.Contains(TEXT("GL_IMG_texture_compression_pvrtc")) ; bSupportsATITC = ExtensionsString.Contains(TEXT("GL_ATI_texture_compression_atitc")) || ExtensionsString.Contains(TEXT("GL_AMD_compressed_ATC_texture")); bSupportsVertexArrayObjects = ExtensionsString.Contains(TEXT("GL_OES_vertex_array_object")) ; bSupportsDiscardFrameBuffer = ExtensionsString.Contains(TEXT("GL_EXT_discard_framebuffer")); bSupportsNVFrameBufferBlit = ExtensionsString.Contains(TEXT("GL_NV_framebuffer_blit")); bSupportsTextureFilterAnisotropic = ExtensionsString.Contains(TEXT("GL_EXT_texture_filter_anisotropic")); bSupportsShaderTextureLod = ExtensionsString.Contains(TEXT("GL_EXT_shader_texture_lod")); bSupportsTextureCubeLodEXT = bSupportsShaderTextureLod; // This never exists in WebGL (ANGLE exports this, so we want to force it to false) bSupportsRGBA8 = false; // This is not color-renderable in WebGL/ANGLE (ANGLE exposes this) bSupportsBGRA8888 = false; // ANGLE/WEBGL_depth_texture is sort of like OES_depth_texture, you just can't upload bulk data to it (via Tex*Image2D); that should be OK? bSupportsDepthTexture = ExtensionsString.Contains(TEXT("GL_ANGLE_depth_texture")) || ExtensionsString.Contains(TEXT("WEBGL_depth_texture")); #if !PLATFORM_HTML5_WIN32 // The core WebGL spec has a combined GL_DEPTH_STENCIL_ATTACHMENT, unlike the core GLES2 spec. bCombinedDepthStencilAttachment = true; // Note that WebGL always supports packed depth stencil renderbuffers (DEPTH_STENCIL renderbuffor format), but for textures // needs WEBGL_depth_texture (at which point it's DEPTH_STENCIL + UNSIGNED_INT_24_8) // @todo: if we can always create PF_DepthStencil as DEPTH_STENCIL renderbuffers, we could remove the dependency bSupportsPackedDepthStencil = bSupportsDepthTexture; #else bCombinedDepthStencilAttachment = false; bSupportsPackedDepthStencil = ExtensionsString.Contains(TEXT("GL_OES_packed_depth_stencil")); #endif if (!ExtensionsString.Contains(TEXT("WEBGL_depth_texture")) && // Catch "WEBGL_depth_texture", "MOZ_WEBGL_depth_texture" and "WEBKIT_WEBGL_depth_texture". !ExtensionsString.Contains(TEXT("GL_ANGLE_depth_texture")) && // for HTML5_WIN32 build with ANGLE !ExtensionsString.Contains(TEXT("GL_OES_depth_texture"))) // for a future HTML5 build without ANGLE { UE_LOG(LogRHI, Warning, TEXT("This browser does not support WEBGL_depth_texture. Rendering will not function since fallback code is not available.")); } // Report shader precision int Range[2]; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_FLOAT, Range, &ShaderLowPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, Range, &ShaderMediumPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, Range, &ShaderHighPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader lowp precision: %d"), ShaderLowPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader mediump precision: %d"), ShaderMediumPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader highp precision: %d"), ShaderHighPrecision); }
void FOpenGLES31::ProcessExtensions( const FString& ExtensionsString ) { // Version setup first, need to check string for 3 or higher, then can use integer queries if (SupportsAdvancedFeatures()) { glGetIntegerv(GL_MAJOR_VERSION, &MajorVersion); glGetIntegerv(GL_MINOR_VERSION, &MinorVersion); bES2Fallback = false; UE_LOG(LogRHI, Log, TEXT("bES2Fallback = false")); } else { MajorVersion = 2; MinorVersion = 0; bES2Fallback = true; UE_LOG(LogRHI, Log, TEXT("bES2Fallback = true")); } bSupportsSeparateAlphaBlend = ExtensionsString.Contains(TEXT("GL_EXT_draw_buffers_indexed")); static auto CVarAllowHighQualityLightMaps = IConsoleManager::Get().FindConsoleVariable(TEXT("r.HighQualityLightMaps")); if (!bES2Fallback) { // only supported if we are at a minimum bar bSupportsTessellation = ExtensionsString.Contains(TEXT("GL_EXT_tessellation_shader")); bSupportsTextureView = ExtensionsString.Contains(TEXT("GL_EXT_texture_view")); CVarAllowHighQualityLightMaps->Set(1); } else { CVarAllowHighQualityLightMaps->Set(0); } ProcessQueryGLInt(); FOpenGLBase::ProcessExtensions(ExtensionsString); bSupportsMapBuffer = ExtensionsString.Contains(TEXT("GL_OES_mapbuffer")); bSupportsDepthTexture = ExtensionsString.Contains(TEXT("GL_OES_depth_texture")); bSupportsOcclusionQueries = ExtensionsString.Contains(TEXT("GL_ARB_occlusion_query2")) || ExtensionsString.Contains(TEXT("GL_EXT_occlusion_query_boolean")); bSupportsRGBA8 = ExtensionsString.Contains(TEXT("GL_OES_rgb8_rgba8")); bSupportsBGRA8888 = ExtensionsString.Contains(TEXT("GL_APPLE_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_IMG_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_format_BGRA8888")); bSupportsVertexHalfFloat = ExtensionsString.Contains(TEXT("GL_OES_vertex_half_float")); bSupportsTextureFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_float")); bSupportsTextureHalfFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_half_float")); bSupportsSGRB = ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsColorBufferHalfFloat = ExtensionsString.Contains(TEXT("GL_EXT_color_buffer_half_float")); bSupportsNvImageFormats = ExtensionsString.Contains(TEXT("GL_NV_image_formats")); bSupportsShaderFramebufferFetch = ExtensionsString.Contains(TEXT("GL_EXT_shader_framebuffer_fetch")) || ExtensionsString.Contains(TEXT("GL_NV_shader_framebuffer_fetch")) || ExtensionsString.Contains(TEXT("GL_ARM_shader_framebuffer_fetch")); bSupportsShaderDepthStencilFetch = ExtensionsString.Contains(TEXT("GL_ARM_shader_framebuffer_fetch_depth_stencil")); bSupportsMultisampledRenderToTexture = ExtensionsString.Contains(TEXT("GL_EXT_multisampled_render_to_texture")); // @todo es3: SRGB support does not work with our texture format setup (ES2 docs indicate that internalFormat and format must match, but they don't at all with sRGB enabled) // One possible solution us to use GLFormat.InternalFormat[bSRGB] instead of GLFormat.Format bSupportsSGRB = false;//ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsDXT = ExtensionsString.Contains(TEXT("GL_NV_texture_compression_s3tc")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_compression_s3tc")); bSupportsPVRTC = ExtensionsString.Contains(TEXT("GL_IMG_texture_compression_pvrtc")) ; bSupportsATITC = ExtensionsString.Contains(TEXT("GL_ATI_texture_compression_atitc")) || ExtensionsString.Contains(TEXT("GL_AMD_compressed_ATC_texture")); bSupportsETC1 = ExtensionsString.Contains(TEXT("GL_OES_compressed_ETC1_RGB8_texture")); bSupportsVertexArrayObjects = ExtensionsString.Contains(TEXT("GL_OES_vertex_array_object")) ; bSupportsDiscardFrameBuffer = ExtensionsString.Contains(TEXT("GL_EXT_discard_framebuffer")); bSupportsNVFrameBufferBlit = ExtensionsString.Contains(TEXT("GL_NV_framebuffer_blit")); bSupportsPackedDepthStencil = ExtensionsString.Contains(TEXT("GL_OES_packed_depth_stencil")); bSupportsShaderTextureLod = ExtensionsString.Contains(TEXT("GL_EXT_shader_texture_lod")); bSupportsTextureStorageEXT = ExtensionsString.Contains(TEXT("GL_EXT_texture_storage")); bSupportsCopyTextureLevels = bSupportsTextureStorageEXT && ExtensionsString.Contains(TEXT("GL_APPLE_copy_texture_levels")); bSupportsDisjointTimeQueries = ExtensionsString.Contains(TEXT("GL_EXT_disjoint_timer_query"));// || ExtensionsString.Contains(TEXT("GL_NV_timer_query")); bTimerQueryCanBeDisjoint = !ExtensionsString.Contains(TEXT("GL_NV_timer_query")); bSupportsNvTimerQuery = ExtensionsString.Contains(TEXT("GL_NV_timer_query")); // Report shader precision int Range[2]; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_FLOAT, Range, &ShaderLowPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, Range, &ShaderMediumPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, Range, &ShaderHighPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader lowp precision: %d"), ShaderLowPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader mediump precision: %d"), ShaderMediumPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader highp precision: %d"), ShaderHighPrecision); // Test whether the GPU can support volume-texture rendering. // There is no API to query this - you just have to test whether a 3D texture is framebuffer-complete. if (!bES2Fallback) { GLuint FrameBuffer; glGenFramebuffers(1, &FrameBuffer); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, FrameBuffer); GLuint VolumeTexture; glGenTextures(1, &VolumeTexture); glBindTexture(GL_TEXTURE_3D, VolumeTexture); glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 256, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glFramebufferTextureEXT(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, VolumeTexture, 0); bSupportsVolumeTextureRendering = (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); glDeleteTextures(1, &VolumeTexture); glDeleteFramebuffers(1, &FrameBuffer); } bSupportsCopyImage = ExtensionsString.Contains(TEXT("GL_EXT_copy_image")); }
void get_shader_precision_format(shader_type_t shadertype, precision_type_t precisiontype, gl::int_t * range, gl::int_t * precision) { glGetShaderPrecisionFormat(static_cast<GLenum>(shadertype), static_cast<GLenum>(precisiontype), range, precision); }
void FHTML5OpenGL::ProcessExtensions( const FString& ExtensionsString ) { FOpenGLES2::ProcessQueryGLInt(); FOpenGLBase::ProcessExtensions(ExtensionsString); bSupportsMapBuffer = ExtensionsString.Contains(TEXT("GL_OES_mapbuffer")); bSupportsDepthTexture = ExtensionsString.Contains(TEXT("GL_OES_depth_texture")); bSupportsOcclusionQueries = ExtensionsString.Contains(TEXT("GL_ARB_occlusion_query2")) || ExtensionsString.Contains(TEXT("GL_EXT_occlusion_query_boolean")); bSupportsRGBA8 = ExtensionsString.Contains(TEXT("GL_OES_rgb8_rgba8")); bSupportsBGRA8888 = ExtensionsString.Contains(TEXT("GL_APPLE_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_IMG_texture_format_BGRA8888")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_format_BGRA8888")); bSupportsVertexHalfFloat = false;//ExtensionsString.Contains(TEXT("GL_OES_vertex_half_float")); bSupportsTextureFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_float")); bSupportsTextureHalfFloat = ExtensionsString.Contains(TEXT("GL_OES_texture_half_float")) && ExtensionsString.Contains(TEXT("GL_OES_texture_half_float_linear")); bSupportsSGRB = ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsColorBufferHalfFloat = ExtensionsString.Contains(TEXT("GL_EXT_color_buffer_half_float")); bSupportsShaderFramebufferFetch = ExtensionsString.Contains(TEXT("GL_EXT_shader_framebuffer_fetch")) || ExtensionsString.Contains(TEXT("GL_NV_shader_framebuffer_fetch")); // @todo ios7: SRGB support does not work with our texture format setup (ES2 docs indicate that internalFormat and format must match, but they don't at all with sRGB enabled) // One possible solution us to use GLFormat.InternalFormat[bSRGB] instead of GLFormat.Format bSupportsSGRB = false;//ExtensionsString.Contains(TEXT("GL_EXT_sRGB")); bSupportsDXT = ExtensionsString.Contains(TEXT("GL_NV_texture_compression_s3tc")) || ExtensionsString.Contains(TEXT("GL_EXT_texture_compression_s3tc")) || ExtensionsString.Contains(TEXT("WEBGL_compressed_texture_s3tc")) || (ExtensionsString.Contains(TEXT("GL_EXT_texture_compression_dxt1")) && // ANGLE (for HTML5_Win32) exposes these 3 as discrete extensions ExtensionsString.Contains(TEXT("GL_ANGLE_texture_compression_dxt3")) && ExtensionsString.Contains(TEXT("GL_ANGLE_texture_compression_dxt5")) ); bSupportsPVRTC = ExtensionsString.Contains(TEXT("GL_IMG_texture_compression_pvrtc")) ; bSupportsATITC = ExtensionsString.Contains(TEXT("GL_ATI_texture_compression_atitc")) || ExtensionsString.Contains(TEXT("GL_AMD_compressed_ATC_texture")); bSupportsVertexArrayObjects = ExtensionsString.Contains(TEXT("GL_OES_vertex_array_object")) ; bSupportsDiscardFrameBuffer = ExtensionsString.Contains(TEXT("GL_EXT_discard_framebuffer")); bSupportsNVFrameBufferBlit = ExtensionsString.Contains(TEXT("GL_NV_framebuffer_blit")); bSupportsShaderTextureLod = ExtensionsString.Contains(TEXT("GL_EXT_shader_texture_lod")); bSupportsTextureCubeLodEXT = bSupportsShaderTextureLod; // This never exists in WebGL (ANGLE exports this, so we want to force it to false) bSupportsRGBA8 = false; // This is not color-renderable in WebGL/ANGLE (ANGLE exposes this) bSupportsBGRA8888 = false; // ANGLE/WEBGL_depth_texture is sort of like OES_depth_texture, you just can't upload bulk data to it (via Tex*Image2D); that should be OK? bSupportsDepthTexture = ExtensionsString.Contains(TEXT("WEBGL_depth_texture")) || // Catch "WEBGL_depth_texture", "MOZ_WEBGL_depth_texture" and "WEBKIT_WEBGL_depth_texture". ExtensionsString.Contains(TEXT("GL_ANGLE_depth_texture")) || // for HTML5_WIN32 build with ANGLE ExtensionsString.Contains(TEXT("GL_OES_depth_texture")); // for a future HTML5 build without ANGLE #if PLATFORM_HTML5_BROWSER // The core WebGL spec has a combined GL_DEPTH_STENCIL_ATTACHMENT, unlike the core GLES2 spec. bCombinedDepthStencilAttachment = true; // Note that WebGL always supports packed depth stencil renderbuffers (DEPTH_STENCIL renderbuffor format), but for textures // needs WEBGL_depth_texture (at which point it's DEPTH_STENCIL + UNSIGNED_INT_24_8) // @todo: if we can always create PF_DepthStencil as DEPTH_STENCIL renderbuffers, we could remove the dependency bSupportsPackedDepthStencil = bSupportsDepthTexture; #else bCombinedDepthStencilAttachment = false; bSupportsPackedDepthStencil = ExtensionsString.Contains(TEXT("GL_OES_packed_depth_stencil")); #endif if (!bSupportsDepthTexture) { UE_LOG(LogRHI, Warning, TEXT("This browser does not support WEBGL_depth_texture. Rendering will not function since fallback code is not available.")); } if (bSupportsTextureHalfFloat && !bSupportsColorBufferHalfFloat) { // Initial implementations of WebGL's texture_float screwed up, and allowed // rendering to fp textures, even though the underlying EXT_texture_float doesn't // explicitly allow anything such. FP rendering without explicit // EXT_color_buffer_half_float may be possible, so we test for that here // by checking for framebuffer completeness. The spec is "wrong" as far as // clamping and the like (which WEBGL_color_buffer_float/EXT_color_buffer_half_float // fixes, but in practice it might "just work"). // // See http://www.khronos.org/webgl/public-mailing-list/archives/1211/msg00133.html // for more information. UE_LOG(LogRHI, Warning, TEXT("Trying to enable fp rendering without explicit EXT_color_buffer_half_float by checking for framebuffer completeness")); GLenum err = glGetError(); if (err != GL_NO_ERROR) { UE_LOG(LogRHI, Warning, TEXT("Detected OpenGL error 0x%04x before checking for implicit half-float fb support"), err); } GLuint tex, fb; #if PLATFORM_HTML5_WIN32 glClearColor( 1.0, 0.5, 0.0,1.0); glClear( GL_COLOR_BUFFER_BIT ); #endif glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_HALF_FLOAT_OES, NULL); glGenFramebuffers(1, &fb); glBindFramebuffer(GL_FRAMEBUFFER, fb); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); GLenum fbstatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); #if PLATFORM_HTML5_WIN32 // keep glReadPixel out of floating point tests for HTML5 Browser builds, glReadPixels doesn't work consistently across browser and is // hidden behind inconsistent webgl extentions. TArray<FLinearColor> Data; Data.AddUninitialized(32*32); glViewport(0, 0, 32, 32); glClear(GL_COLOR_BUFFER_BIT); FMemory::Memzero(Data.GetData(),32*32*sizeof(FLinearColor)); glReadPixels(0, 0, 32, 32, GL_RGBA, GL_FLOAT, Data.GetData()); err = glGetError(); UE_LOG(LogRHI, Log, TEXT(" %f %f %f %f"), Data[0].R,Data[0].G,Data[0].B,Data[0].A); #endif bSupportsColorBufferHalfFloat = fbstatus == GL_FRAMEBUFFER_COMPLETE && err == GL_NO_ERROR; if (bSupportsColorBufferHalfFloat) { UE_LOG(LogRHI, Log, TEXT("Enabling implicit ColorBufferHalfFloat after checking fb completeness")); } else { UE_LOG(LogRHI, Log, TEXT("Could not enable implicit ColorBufferHalfFloat after checking fb completeness")); } glBindFramebuffer(GL_FRAMEBUFFER, 0); glDeleteFramebuffers(1, &fb); glDeleteTextures(1, &tex); } // Report shader precision int Range[2]; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_LOW_FLOAT, Range, &ShaderLowPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, Range, &ShaderMediumPrecision); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, Range, &ShaderHighPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader lowp precision: %d"), ShaderLowPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader mediump precision: %d"), ShaderMediumPrecision); UE_LOG(LogRHI, Log, TEXT("Fragment shader highp precision: %d"), ShaderHighPrecision); }
void piglit_init(int argc, char **argv) { #ifdef GL_ARB_ES2_compatibility GLboolean pass = GL_TRUE; GLint status; unsigned i; unsigned j; static const GLenum shaderTypes[] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; static const struct { GLenum type; GLint range[2]; GLint precision; } precision[] = { { GL_LOW_FLOAT, { 1, 1 }, 8 }, { GL_MEDIUM_FLOAT, { 14, 14 }, 10 }, { GL_HIGH_FLOAT, { 62, 62 }, 16 }, { GL_LOW_INT, { 8, 8 }, 0 }, { GL_MEDIUM_INT, { 10, 10 }, 0 }, { GL_HIGH_INT, { 16, 16 }, 0 } }; piglit_require_gl_version(20); if (!piglit_is_extension_supported("GL_ARB_ES2_compatibility")) { printf("Requires ARB_ES2_compatibility\n"); piglit_report_result(PIGLIT_SKIP); } for (i = 0; i < ARRAY_SIZE(shaderTypes); i++) { for (j = 0; j < ARRAY_SIZE(precision); j++) { GLint r[2]; GLint p; r[0] = 0; r[1] = 0; p = 0; glGetShaderPrecisionFormat(GL_VERTEX_SHADER, precision[j].type, r, & p); status = glGetError(); if (status != GL_NO_ERROR) { printf("glGetShaderPrecisionFormat(0x%04x, " "0x%04x) " "got GL error of 0x%04x\n", shaderTypes[i], precision[j].type, status); pass = GL_FALSE; } if (r[0] < precision[j].range[0] || r[1] < precision[j].range[1] || p < precision[j].precision) { printf("glGetShaderPrecisionFormat(0x%04x, " "0x%04x) " "returned invalid values:\n" " range = { %d, %d }\n" " precision = %d\n" "expected at least:\n" " range = { %d, %d }\n" " precision = %d\n", shaderTypes[i], precision[j].type, r[0], r[1], p, precision[j].range[0], precision[j].range[1], precision[j].precision); pass = GL_FALSE; } } } piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); #else piglit_report_result(PIGLIT_SKIP); #endif /* GL_ARB_ES2_compatibility */ }
/** Loads a single shader. This is NOT cached, use addShaderFile for that. * \param file Filename of the shader to load. * \param type Type of the shader. */ GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type) { const GLuint id = glCreateShader(type); std::ostringstream code; #if !defined(USE_GLES2) code << "#version " << CVS->getGLSLVersion()<<"\n"; #else if (CVS->isGLSL()) code << "#version 300 es\n"; #endif #if !defined(USE_GLES2) // Some drivers report that the compute shaders extension is available, // but they report only OpenGL 3.x version, and thus these extensions // must be enabled manually. Otherwise the shaders compilation will fail // because STK tries to use extensions which are available, but disabled // by default. if (type == GL_COMPUTE_SHADER) { if (CVS->isARBComputeShaderUsable()) code << "#extension GL_ARB_compute_shader : enable\n"; if (CVS->isARBImageLoadStoreUsable()) code << "#extension GL_ARB_shader_image_load_store : enable\n"; if (CVS->isARBArraysOfArraysUsable()) code << "#extension GL_ARB_arrays_of_arrays : enable\n"; } #endif if (CVS->isAMDVertexShaderLayerUsable()) code << "#extension GL_AMD_vertex_shader_layer : enable\n"; if (CVS->isARBExplicitAttribLocationUsable()) { #if !defined(USE_GLES2) code << "#extension GL_ARB_explicit_attrib_location : enable\n"; #endif code << "#define Explicit_Attrib_Location_Usable\n"; } if (CVS->isAZDOEnabled()) { code << "#extension GL_ARB_bindless_texture : enable\n"; code << "#define Use_Bindless_Texture\n"; } code << "//" << file << "\n"; if (!CVS->isARBUniformBufferObjectUsable()) code << "#define UBO_DISABLED\n"; if (CVS->isAMDVertexShaderLayerUsable()) code << "#define VSLayer\n"; if (CVS->needsRGBBindlessWorkaround()) code << "#define SRGBBindlessFix\n"; if (CVS->isDefferedEnabled()) code << "#define Advanced_Lighting_Enabled\n"; #if !defined(USE_GLES2) // shader compilation fails with some drivers if there is no precision // qualifier if (type == GL_FRAGMENT_SHADER) code << "precision highp float;\n"; #else int range[2], precision; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision); if (precision > 0) code << "precision highp float;\n"; else code << "precision mediump float;\n"; #endif code << "#define MAX_BONES " << SharedGPUObjects::getMaxMat4Size() << "\n"; code << getHeader(); readFile(file, code); Log::info("ShaderFilesManager", "Compiling shader : %s", file.c_str()); const std::string &source = code.str(); char const *source_pointer = source.c_str(); int len = source.size(); glShaderSource(id, 1, &source_pointer, &len); glCompileShader(id); GLint result = GL_FALSE; glGetShaderiv(id, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { // failed to compile int info_length; Log::error("ShaderFilesManager", "Error in shader %s", file.c_str()); glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length); if (info_length < 0) info_length = 1024; char *error_message = new char[info_length]; error_message[0] = 0; glGetShaderInfoLog(id, info_length, NULL, error_message); Log::error("ShaderFilesManager", error_message); delete[] error_message; } glGetError(); return id; } // loadShader
/** Loads a single shader. This is NOT cached, use addShaderFile for that. * \param file Filename of the shader to load. * \param type Type of the shader. */ ShaderFilesManager::SharedShader ShaderFilesManager::loadShader (const std::string& full_path, unsigned type) { GLuint* ss_ptr = new GLuint; *ss_ptr = glCreateShader(type); SharedShader ss(ss_ptr, [](GLuint* ss) { glDeleteShader(*ss); delete ss; }); std::ostringstream code; #if !defined(USE_GLES2) code << "#version " << CVS->getGLSLVersion()<<"\n"; #else if (CVS->isGLSL()) code << "#version 300 es\n"; #endif #if !defined(USE_GLES2) // Some drivers report that the compute shaders extension is available, // but they report only OpenGL 3.x version, and thus these extensions // must be enabled manually. Otherwise the shaders compilation will fail // because STK tries to use extensions which are available, but disabled // by default. if (type == GL_COMPUTE_SHADER) { if (CVS->isARBComputeShaderUsable()) code << "#extension GL_ARB_compute_shader : enable\n"; if (CVS->isARBImageLoadStoreUsable()) code << "#extension GL_ARB_shader_image_load_store : enable\n"; if (CVS->isARBArraysOfArraysUsable()) code << "#extension GL_ARB_arrays_of_arrays : enable\n"; } #endif if (CVS->isARBExplicitAttribLocationUsable()) { #if !defined(USE_GLES2) code << "#extension GL_ARB_explicit_attrib_location : enable\n"; #endif code << "#define Explicit_Attrib_Location_Usable\n"; } if (GraphicsRestrictions::isDisabled (GraphicsRestrictions::GR_CORRECT_10BIT_NORMALIZATION)) { code << "#define Converts_10bit_Vector\n"; } code << "//" << full_path << "\n"; if (!CVS->isARBUniformBufferObjectUsable()) code << "#define UBO_DISABLED\n"; if (!CVS->isARBTextureBufferObjectUsable()) code << "#define TBO_DISABLED\n"; if (CVS->needsVertexIdWorkaround()) code << "#define Needs_Vertex_Id_Workaround\n"; if (CVS->isDeferredEnabled()) code << "#define Advanced_Lighting_Enabled\n"; #if !defined(USE_GLES2) // shader compilation fails with some drivers if there is no precision // qualifier if (type == GL_FRAGMENT_SHADER) code << "precision highp float;\n"; #else int range[2], precision; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision); if (precision > 0) { code << "precision highp float;\n"; code << "precision highp sampler2DArrayShadow;\n"; code << "precision highp sampler2DArray;\n"; } else { code << "precision mediump float;\n"; code << "precision mediump sampler2DArrayShadow;\n"; code << "precision mediump sampler2DArray;\n"; } #endif code << "#define MAX_BONES " << stk_config->m_max_skinning_bones << "\n"; code << getHeader(); readFile(full_path, code); Log::info("ShaderFilesManager", "Compiling shader: %s", full_path.c_str()); const std::string &source = code.str(); char const *source_pointer = source.c_str(); int len = (int)source.size(); glShaderSource(*ss, 1, &source_pointer, &len); glCompileShader(*ss); GLint result = GL_FALSE; glGetShaderiv(*ss, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { // failed to compile int info_length; Log::error("ShaderFilesManager", "Error in shader %s", full_path.c_str()); glGetShaderiv(*ss, GL_INFO_LOG_LENGTH, &info_length); if (info_length < 0) info_length = 1024; char *error_message = new char[info_length]; error_message[0] = 0; glGetShaderInfoLog(*ss, info_length, NULL, error_message); Log::error("ShaderFilesManager", error_message); delete[] error_message; if (UserConfigParams::m_artist_debug_mode) { core::stringw err = StringUtils::insertValues(L"Shader file %s" " failed to compile, check stdout.log or console for details", full_path.c_str()); MessageQueue::add(MessageQueue::MT_ERROR, err); } return NULL; } glGetError(); return ss; } // loadShader
void CheckGLExtensions() { #if !PPSSPP_PLATFORM(UWP) // Make sure to only do this once. It's okay to call CheckGLExtensions from wherever. if (extensionsDone) return; extensionsDone = true; memset(&gl_extensions, 0, sizeof(gl_extensions)); gl_extensions.IsCoreContext = useCoreContext; #ifdef USING_GLES2 gl_extensions.IsGLES = true; #endif const char *renderer = (const char *)glGetString(GL_RENDERER); const char *versionStr = (const char *)glGetString(GL_VERSION); const char *glslVersionStr = (const char *)glGetString(GL_SHADING_LANGUAGE_VERSION); // Check vendor string to try and guess GPU const char *cvendor = (char *)glGetString(GL_VENDOR); // TODO: move this stuff to gpu_features.cpp if (cvendor) { const std::string vendor = StripSpaces(std::string(cvendor)); if (vendor == "NVIDIA Corporation" || vendor == "Nouveau" || vendor == "nouveau") { gl_extensions.gpuVendor = GPU_VENDOR_NVIDIA; } else if (vendor == "Advanced Micro Devices, Inc." || vendor == "ATI Technologies Inc.") { gl_extensions.gpuVendor = GPU_VENDOR_AMD; } else if (vendor == "Intel" || vendor == "Intel Inc." || vendor == "Intel Corporation" || vendor == "Tungsten Graphics, Inc") { // We'll assume this last one means Intel gl_extensions.gpuVendor = GPU_VENDOR_INTEL; } else if (vendor == "ARM") { gl_extensions.gpuVendor = GPU_VENDOR_ARM; } else if (vendor == "Imagination Technologies") { gl_extensions.gpuVendor = GPU_VENDOR_POWERVR; } else if (vendor == "Qualcomm") { gl_extensions.gpuVendor = GPU_VENDOR_ADRENO; } else if (vendor == "Broadcom") { gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM; // Just for reference: Galaxy Y has renderer == "VideoCore IV HW" } else { gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; } } else { gl_extensions.gpuVendor = GPU_VENDOR_UNKNOWN; } ILOG("GPU Vendor : %s ; renderer: %s version str: %s ; GLSL version str: %s", cvendor, renderer ? renderer : "N/A", versionStr ? versionStr : "N/A", glslVersionStr ? glslVersionStr : "N/A"); if (renderer) { strncpy(gl_extensions.model, renderer, sizeof(gl_extensions.model)); gl_extensions.model[sizeof(gl_extensions.model) - 1] = 0; } if (!gl_extensions.IsGLES) { // For desktop GL, grab the version and attempt to parse. char buffer[64] = { 0 }; if (versionStr) { strncpy(buffer, versionStr, 63); } const char *lastNumStart = buffer; int numVer = 0; int len = (int)strlen(buffer); for (int i = 0; i < len && numVer < 3; i++) { if (buffer[i] == '.') { buffer[i] = 0; gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); i++; lastNumStart = buffer + i; } } if (numVer < 3) gl_extensions.ver[numVer++] = strtol(lastNumStart, NULL, 10); // If the GL version >= 4.3, we know it's a true superset of OpenGL ES 3.0 and can thus enable // all the same modern paths. // Most of it could be enabled on lower GPUs as well, but let's start this way. if (gl_extensions.VersionGEThan(4, 3, 0)) { gl_extensions.GLES3 = true; } } else { // Start by assuming we're at 2.0. gl_extensions.ver[0] = 2; #ifdef USING_GLES2 #ifdef GL_MAJOR_VERSION // Before grabbing the values, reset the error. glGetError(); glGetIntegerv(GL_MAJOR_VERSION, &gl_extensions.ver[0]); glGetIntegerv(GL_MINOR_VERSION, &gl_extensions.ver[1]); // We check error here to detect if these properties were supported. if (glGetError() != GL_NO_ERROR) { // They weren't, reset to GLES 2.0. gl_extensions.ver[0] = 2; gl_extensions.ver[1] = 0; } #endif // If the above didn't give us a version, or gave us a crazy version, fallback. if (gl_extensions.ver[0] < 3 || gl_extensions.ver[0] > 5) { // Try to load GLES 3.0 only if "3.0" found in version // This simple heuristic avoids issues on older devices where you can only call eglGetProcAddress a limited // number of times. Make sure to check for 3.0 in the shader version too to avoid false positives, see #5584. bool gl_3_0_in_string = strstr(versionStr, "3.0") && strstr(glslVersionStr, "3.0"); bool gl_3_1_in_string = strstr(versionStr, "3.1") && strstr(glslVersionStr, "3.1"); // intentionally left out .1 if ((gl_3_0_in_string || gl_3_1_in_string) && gl3stubInit()) { gl_extensions.ver[0] = 3; if (gl_3_1_in_string) { gl_extensions.ver[1] = 1; } gl_extensions.GLES3 = true; // Though, let's ban Mali from the GLES 3 path for now, see #4078 if (strstr(renderer, "Mali") != 0) { gl_extensions.GLES3 = false; } } else { // Just to be safe. gl_extensions.ver[0] = 2; gl_extensions.ver[1] = 0; } } else { // Otherwise, let's trust GL_MAJOR_VERSION. Note that Mali is intentionally not banned here. if (gl_extensions.ver[0] >= 3) { gl_extensions.GLES3 = gl3stubInit(); } } #endif if (gl_extensions.GLES3) { if (gl_extensions.ver[1] >= 1) { ILOG("OpenGL ES 3.1 support detected!\n"); } else { ILOG("OpenGL ES 3.0 support detected!\n"); } } } const char *extString = nullptr; if (gl_extensions.ver[0] >= 3) { // Let's use the new way for OpenGL 3.x+, required in the core profile. GLint numExtensions = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); g_all_gl_extensions = ""; for (GLint i = 0; i < numExtensions; ++i) { g_all_gl_extensions += (const char *)glGetStringi(GL_EXTENSIONS, i); g_all_gl_extensions += " "; } extString = g_all_gl_extensions.c_str(); } else { extString = (const char *)glGetString(GL_EXTENSIONS); if (extString) { g_all_gl_extensions = extString; } else { g_all_gl_extensions = ""; extString = ""; } } #ifdef WIN32 const char *wglString = 0; if (wglGetExtensionsStringEXT) wglString = wglGetExtensionsStringEXT(); if (wglString) { gl_extensions.EXT_swap_control_tear = strstr(wglString, "WGL_EXT_swap_control_tear") != 0; g_all_egl_extensions = wglString; } else { g_all_egl_extensions = ""; } #elif !defined(USING_GLES2) // const char *glXString = glXQueryExtensionString(); // gl_extensions.EXT_swap_control_tear = strstr(glXString, "GLX_EXT_swap_control_tear") != 0; #endif // Check the desktop extension instead of the OES one. They are very similar. // Also explicitly check those ATI devices that claims to support npot gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0 && !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0))); gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0; gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0; gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; gl_extensions.OES_copy_image = strstr(extString, "GL_OES_copy_image") != 0; gl_extensions.EXT_copy_image = strstr(extString, "GL_EXT_copy_image") != 0; gl_extensions.ARB_copy_image = strstr(extString, "GL_ARB_copy_image") != 0; gl_extensions.ARB_vertex_array_object = strstr(extString, "GL_ARB_vertex_array_object") != 0; gl_extensions.ARB_texture_float = strstr(extString, "GL_ARB_texture_float") != 0; if (gl_extensions.IsGLES) { gl_extensions.OES_texture_npot = strstr(extString, "GL_OES_texture_npot") != 0; gl_extensions.OES_packed_depth_stencil = (strstr(extString, "GL_OES_packed_depth_stencil") != 0) || gl_extensions.GLES3; gl_extensions.OES_depth24 = strstr(extString, "GL_OES_depth24") != 0; gl_extensions.OES_depth_texture = strstr(extString, "GL_OES_depth_texture") != 0; gl_extensions.OES_mapbuffer = strstr(extString, "GL_OES_mapbuffer") != 0; gl_extensions.EXT_blend_minmax = strstr(extString, "GL_EXT_blend_minmax") != 0; gl_extensions.EXT_unpack_subimage = strstr(extString, "GL_EXT_unpack_subimage") != 0; gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; gl_extensions.OES_texture_float = strstr(extString, "GL_OES_texture_float") != 0; gl_extensions.OES_texture_half_float = strstr(extString, "GL_OES_texture_half_float") != 0; #if defined(__ANDROID__) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 #ifdef _DEBUG void *invalidAddress = (void *)eglGetProcAddress("InvalidGlCall1"); void *invalidAddress2 = (void *)eglGetProcAddress("AnotherInvalidGlCall2"); DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); #endif // These are all the same. Let's alias. if (!gl_extensions.OES_copy_image) { if (gl_extensions.NV_copy_image) { glCopyImageSubDataOES = (decltype(glCopyImageSubDataOES))eglGetProcAddress("glCopyImageSubDataNV"); } else if (gl_extensions.EXT_copy_image) { glCopyImageSubDataOES = (decltype(glCopyImageSubDataOES))eglGetProcAddress("glCopyImageSubDataEXT"); } } if (gl_extensions.NV_framebuffer_blit) { glBlitFramebufferNV = (PFNGLBLITFRAMEBUFFERNVPROC)eglGetProcAddress("glBlitFramebufferNV"); } gl_extensions.OES_vertex_array_object = strstr(extString, "GL_OES_vertex_array_object") != 0; if (gl_extensions.OES_vertex_array_object) { glGenVertexArraysOES = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES"); glBindVertexArrayOES = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES"); glDeleteVertexArraysOES = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); glIsVertexArrayOES = (PFNGLISVERTEXARRAYOESPROC)eglGetProcAddress("glIsVertexArrayOES"); } // Hm, this should be available on iOS too. gl_extensions.EXT_discard_framebuffer = strstr(extString, "GL_EXT_discard_framebuffer") != 0; if (gl_extensions.EXT_discard_framebuffer) { glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)eglGetProcAddress("glDiscardFramebufferEXT"); } #else gl_extensions.OES_vertex_array_object = false; gl_extensions.EXT_discard_framebuffer = false; #endif } else { // Desktops support minmax and subimage unpack (GL_UNPACK_ROW_LENGTH etc) gl_extensions.EXT_blend_minmax = true; gl_extensions.EXT_unpack_subimage = true; } // GLES 3 subsumes many ES2 extensions. if (gl_extensions.GLES3) { gl_extensions.EXT_unpack_subimage = true; } #if defined(__ANDROID__) if (gl_extensions.OES_mapbuffer) { glMapBuffer = (PFNGLMAPBUFFERPROC)eglGetProcAddress("glMapBufferOES"); } // Look for EGL extensions EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); const char *eglString = eglQueryString(display, EGL_EXTENSIONS); if (eglString) { g_all_egl_extensions = eglString; gl_extensions.EGL_NV_system_time = strstr(eglString, "EGL_NV_system_time") != 0; gl_extensions.EGL_NV_coverage_sample = strstr(eglString, "EGL_NV_coverage_sample") != 0; if (gl_extensions.EGL_NV_system_time) { eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC)eglGetProcAddress("eglGetSystemTimeNV"); eglGetSystemTimeFrequencyNV = (PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)eglGetProcAddress("eglGetSystemTimeFrequencyNV"); } } else { g_all_egl_extensions = ""; } #endif // This is probably a waste of time, implementations lie. if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) { const GLint precisions[6] = { GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, GL_LOW_INT, GL_MEDIUM_INT, GL_HIGH_INT }; GLint shaderTypes[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER }; for (int st = 0; st < 2; st++) { for (int p = 0; p < 6; p++) { glGetShaderPrecisionFormat(shaderTypes[st], precisions[p], gl_extensions.range[st][p], &gl_extensions.precision[st][p]); } } } gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0; gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0; gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0; if (!gl_extensions.IsGLES && gl_extensions.IsCoreContext) { // These are required, and don't need to be specified by the driver (they aren't on Apple.) gl_extensions.ARB_vertex_array_object = true; gl_extensions.ARB_framebuffer_object = true; } #ifdef __APPLE__ if (!gl_extensions.IsGLES && !gl_extensions.IsCoreContext) { // Apple doesn't allow OpenGL 3.x+ in compatibility contexts. gl_extensions.ForceGL2 = true; } #endif ProcessGPUFeatures(); int error = glGetError(); if (error) ELOG("GL error in init: %i", error); #endif }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GL41_nglGetShaderPrecisionFormat(JNIEnv *env, jclass clazz, jint shadertype, jint precisiontype, jlong range, jlong precision, jlong function_pointer) { GLint *range_address = (GLint *)(intptr_t)range; GLint *precision_address = (GLint *)(intptr_t)precision; glGetShaderPrecisionFormatPROC glGetShaderPrecisionFormat = (glGetShaderPrecisionFormatPROC)((intptr_t)function_pointer); glGetShaderPrecisionFormat(shadertype, precisiontype, range_address, precision_address); }
uintptr_t processFn(struct fnargs* args, char* parg) { uintptr_t ret = 0; switch (args->fn) { case glfnUNDEFINED: abort(); // bad glfn break; case glfnActiveTexture: glActiveTexture((GLenum)args->a0); break; case glfnAttachShader: glAttachShader((GLint)args->a0, (GLint)args->a1); break; case glfnBindAttribLocation: glBindAttribLocation((GLint)args->a0, (GLint)args->a1, (GLchar*)args->a2); break; case glfnBindBuffer: glBindBuffer((GLenum)args->a0, (GLuint)args->a1); break; case glfnBindFramebuffer: glBindFramebuffer((GLenum)args->a0, (GLint)args->a1); break; case glfnBindRenderbuffer: glBindRenderbuffer((GLenum)args->a0, (GLint)args->a1); break; case glfnBindTexture: glBindTexture((GLenum)args->a0, (GLint)args->a1); break; case glfnBlendColor: glBlendColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnBlendEquation: glBlendEquation((GLenum)args->a0); break; case glfnBlendEquationSeparate: glBlendEquationSeparate((GLenum)args->a0, (GLenum)args->a1); break; case glfnBlendFunc: glBlendFunc((GLenum)args->a0, (GLenum)args->a1); break; case glfnBlendFuncSeparate: glBlendFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); break; case glfnBufferData: glBufferData((GLenum)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg, (GLenum)args->a2); break; case glfnBufferSubData: glBufferSubData((GLenum)args->a0, (GLint)args->a1, (GLsizeiptr)args->a2, (GLvoid*)parg); break; case glfnCheckFramebufferStatus: ret = glCheckFramebufferStatus((GLenum)args->a0); break; case glfnClear: glClear((GLenum)args->a0); break; case glfnClearColor: glClearColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnClearDepthf: glClearDepthf(*(GLfloat*)&args->a0); break; case glfnClearStencil: glClearStencil((GLint)args->a0); break; case glfnColorMask: glColorMask((GLboolean)args->a0, (GLboolean)args->a1, (GLboolean)args->a2, (GLboolean)args->a3); break; case glfnCompileShader: glCompileShader((GLint)args->a0); break; case glfnCompressedTexImage2D: glCompressedTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLsizeiptr)args->a6, (GLvoid*)parg); break; case glfnCompressedTexSubImage2D: glCompressedTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLenum)args->a6, (GLsizeiptr)args->a7, (GLvoid*)parg); break; case glfnCopyTexImage2D: glCopyTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); break; case glfnCopyTexSubImage2D: glCopyTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); break; case glfnCreateProgram: ret = glCreateProgram(); break; case glfnCreateShader: ret = glCreateShader((GLenum)args->a0); break; case glfnCullFace: glCullFace((GLenum)args->a0); break; case glfnDeleteBuffer: glDeleteBuffers(1, (const GLuint*)(&args->a0)); break; case glfnDeleteFramebuffer: glDeleteFramebuffers(1, (const GLuint*)(&args->a0)); break; case glfnDeleteProgram: glDeleteProgram((GLint)args->a0); break; case glfnDeleteRenderbuffer: glDeleteRenderbuffers(1, (const GLuint*)(&args->a0)); break; case glfnDeleteShader: glDeleteShader((GLint)args->a0); break; case glfnDeleteTexture: glDeleteTextures(1, (const GLuint*)(&args->a0)); break; case glfnDepthFunc: glDepthFunc((GLenum)args->a0); break; case glfnDepthMask: glDepthMask((GLboolean)args->a0); break; case glfnDepthRangef: glDepthRangef(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); break; case glfnDetachShader: glDetachShader((GLint)args->a0, (GLint)args->a1); break; case glfnDisable: glDisable((GLenum)args->a0); break; case glfnDisableVertexAttribArray: glDisableVertexAttribArray((GLint)args->a0); break; case glfnDrawArrays: glDrawArrays((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2); break; case glfnDrawElements: glDrawElements((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (void*)args->a3); break; case glfnEnable: glEnable((GLenum)args->a0); break; case glfnEnableVertexAttribArray: glEnableVertexAttribArray((GLint)args->a0); break; case glfnFinish: glFinish(); break; case glfnFlush: glFlush(); break; case glfnFramebufferRenderbuffer: glFramebufferRenderbuffer((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3); break; case glfnFramebufferTexture2D: glFramebufferTexture2D((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4); break; case glfnFrontFace: glFrontFace((GLenum)args->a0); break; case glfnGenBuffer: glGenBuffers(1, (GLuint*)&ret); break; case glfnGenFramebuffer: glGenFramebuffers(1, (GLuint*)&ret); break; case glfnGenRenderbuffer: glGenRenderbuffers(1, (GLuint*)&ret); break; case glfnGenTexture: glGenTextures(1, (GLuint*)&ret); break; case glfnGenerateMipmap: glGenerateMipmap((GLenum)args->a0); break; case glfnGetActiveAttrib: glGetActiveAttrib( (GLuint)args->a0, (GLuint)args->a1, (GLsizei)args->a2, NULL, (GLint*)&ret, (GLenum*)args->a3, (GLchar*)parg); break; case glfnGetActiveUniform: glGetActiveUniform( (GLuint)args->a0, (GLuint)args->a1, (GLsizei)args->a2, NULL, (GLint*)&ret, (GLenum*)args->a3, (GLchar*)parg); break; case glfnGetAttachedShaders: glGetAttachedShaders((GLuint)args->a0, (GLsizei)args->a1, (GLsizei*)&ret, (GLuint*)parg); break; case glfnGetAttribLocation: ret = glGetAttribLocation((GLint)args->a0, (GLchar*)args->a1); break; case glfnGetBooleanv: glGetBooleanv((GLenum)args->a0, (GLboolean*)parg); break; case glfnGetBufferParameteri: glGetBufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetFloatv: glGetFloatv((GLenum)args->a0, (GLfloat*)parg); break; case glfnGetIntegerv: glGetIntegerv((GLenum)args->a0, (GLint*)parg); break; case glfnGetError: ret = glGetError(); break; case glfnGetFramebufferAttachmentParameteriv: glGetFramebufferAttachmentParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint*)&ret); break; case glfnGetProgramiv: glGetProgramiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetProgramInfoLog: glGetProgramInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); break; case glfnGetRenderbufferParameteriv: glGetRenderbufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetShaderiv: glGetShaderiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); break; case glfnGetShaderInfoLog: glGetShaderInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); break; case glfnGetShaderPrecisionFormat: glGetShaderPrecisionFormat((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg, &((GLint*)parg)[2]); break; case glfnGetShaderSource: glGetShaderSource((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); break; case glfnGetString: ret = (uintptr_t)glGetString((GLenum)args->a0); break; case glfnGetTexParameterfv: glGetTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); break; case glfnGetTexParameteriv: glGetTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); break; case glfnGetUniformfv: glGetUniformfv((GLuint)args->a0, (GLint)args->a1, (GLfloat*)parg); break; case glfnGetUniformiv: glGetUniformiv((GLuint)args->a0, (GLint)args->a1, (GLint*)parg); break; case glfnGetUniformLocation: ret = glGetUniformLocation((GLint)args->a0, (GLchar*)args->a1); break; case glfnGetVertexAttribfv: glGetVertexAttribfv((GLuint)args->a0, (GLenum)args->a1, (GLfloat*)parg); break; case glfnGetVertexAttribiv: glGetVertexAttribiv((GLuint)args->a0, (GLenum)args->a1, (GLint*)parg); break; case glfnHint: glHint((GLenum)args->a0, (GLenum)args->a1); break; case glfnIsBuffer: ret = glIsBuffer((GLint)args->a0); break; case glfnIsEnabled: ret = glIsEnabled((GLenum)args->a0); break; case glfnIsFramebuffer: ret = glIsFramebuffer((GLint)args->a0); break; case glfnIsProgram: ret = glIsProgram((GLint)args->a0); break; case glfnIsRenderbuffer: ret = glIsRenderbuffer((GLint)args->a0); break; case glfnIsShader: ret = glIsShader((GLint)args->a0); break; case glfnIsTexture: ret = glIsTexture((GLint)args->a0); break; case glfnLineWidth: glLineWidth(*(GLfloat*)&args->a0); break; case glfnLinkProgram: glLinkProgram((GLint)args->a0); break; case glfnPixelStorei: glPixelStorei((GLenum)args->a0, (GLint)args->a1); break; case glfnPolygonOffset: glPolygonOffset(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); break; case glfnReadPixels: glReadPixels((GLint)args->a0, (GLint)args->a1, (GLsizei)args->a2, (GLsizei)args->a3, (GLenum)args->a4, (GLenum)args->a5, (void*)parg); break; case glfnReleaseShaderCompiler: glReleaseShaderCompiler(); break; case glfnRenderbufferStorage: glRenderbufferStorage((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLint)args->a3); break; case glfnSampleCoverage: glSampleCoverage(*(GLfloat*)&args->a0, (GLboolean)args->a1); break; case glfnScissor: glScissor((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); break; case glfnShaderSource: #if defined(os_ios) || defined(os_osx) glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar *const *)args->a2, NULL); #else glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar **)args->a2, NULL); #endif break; case glfnStencilFunc: glStencilFunc((GLenum)args->a0, (GLint)args->a1, (GLuint)args->a2); break; case glfnStencilFuncSeparate: glStencilFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLuint)args->a3); break; case glfnStencilMask: glStencilMask((GLuint)args->a0); break; case glfnStencilMaskSeparate: glStencilMaskSeparate((GLenum)args->a0, (GLuint)args->a1); break; case glfnStencilOp: glStencilOp((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2); break; case glfnStencilOpSeparate: glStencilOpSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); break; case glfnTexImage2D: glTexImage2D( (GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLsizei)args->a3, (GLsizei)args->a4, 0, // border (GLenum)args->a5, (GLenum)args->a6, (const GLvoid*)parg); break; case glfnTexSubImage2D: glTexSubImage2D( (GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLsizei)args->a4, (GLsizei)args->a5, (GLenum)args->a6, (GLenum)args->a7, (const GLvoid*)parg); break; case glfnTexParameterf: glTexParameterf((GLenum)args->a0, (GLenum)args->a1, *(GLfloat*)&args->a2); break; case glfnTexParameterfv: glTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); break; case glfnTexParameteri: glTexParameteri((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2); break; case glfnTexParameteriv: glTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); break; case glfnUniform1f: glUniform1f((GLint)args->a0, *(GLfloat*)&args->a1); break; case glfnUniform1fv: glUniform1fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform1i: glUniform1i((GLint)args->a0, (GLint)args->a1); break; case glfnUniform1iv: glUniform1iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform2f: glUniform2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); break; case glfnUniform2fv: glUniform2fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform2i: glUniform2i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2); break; case glfnUniform2iv: glUniform2iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform3f: glUniform3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnUniform3fv: glUniform3fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform3i: glUniform3i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); break; case glfnUniform3iv: glUniform3iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform4f: glUniform4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); break; case glfnUniform4fv: glUniform4fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniform4i: glUniform4i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4); break; case glfnUniform4iv: glUniform4iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); break; case glfnUniformMatrix2fv: glUniformMatrix2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); break; case glfnUniformMatrix3fv: glUniformMatrix3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); break; case glfnUniformMatrix4fv: glUniformMatrix4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); break; case glfnUseProgram: glUseProgram((GLint)args->a0); break; case glfnValidateProgram: glValidateProgram((GLint)args->a0); break; case glfnVertexAttrib1f: glVertexAttrib1f((GLint)args->a0, *(GLfloat*)&args->a1); break; case glfnVertexAttrib1fv: glVertexAttrib1fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttrib2f: glVertexAttrib2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); break; case glfnVertexAttrib2fv: glVertexAttrib2fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttrib3f: glVertexAttrib3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); break; case glfnVertexAttrib3fv: glVertexAttrib3fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttrib4f: glVertexAttrib4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); break; case glfnVertexAttrib4fv: glVertexAttrib4fv((GLint)args->a0, (GLfloat*)parg); break; case glfnVertexAttribPointer: glVertexAttribPointer((GLuint)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLboolean)args->a3, (GLsizei)args->a4, (const GLvoid*)args->a5); break; case glfnViewport: glViewport((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); break; } return ret; }
/** Loads a single shader. This is NOT cached, use addShaderFile for that. * \param file Filename of the shader to load. * \param type Type of the shader. */ GLuint ShaderFilesManager::loadShader(const std::string &file, unsigned type) { const GLuint id = glCreateShader(type); std::ostringstream code; #if !defined(USE_GLES2) code << "#version " << CVS->getGLSLVersion()<<"\n"; #else if (CVS->isGLSL()) code << "#version 300 es\n"; #endif #if !defined(USE_GLES2) // Some drivers report that the compute shaders extension is available, // but they report only OpenGL 3.x version, and thus these extensions // must be enabled manually. Otherwise the shaders compilation will fail // because STK tries to use extensions which are available, but disabled // by default. if (type == GL_COMPUTE_SHADER) { if (CVS->isARBComputeShaderUsable()) code << "#extension GL_ARB_compute_shader : enable\n"; if (CVS->isARBImageLoadStoreUsable()) code << "#extension GL_ARB_shader_image_load_store : enable\n"; if (CVS->isARBArraysOfArraysUsable()) code << "#extension GL_ARB_arrays_of_arrays : enable\n"; } #endif if (CVS->isAMDVertexShaderLayerUsable()) code << "#extension GL_AMD_vertex_shader_layer : enable\n"; if (CVS->isARBExplicitAttribLocationUsable()) code << "#extension GL_ARB_explicit_attrib_location : enable\n"; if (CVS->isAZDOEnabled()) { code << "#extension GL_ARB_bindless_texture : enable\n"; code << "#define Use_Bindless_Texture\n"; } code << "//" << file << "\n"; if (!CVS->isARBUniformBufferObjectUsable()) code << "#define UBO_DISABLED\n"; if (CVS->isAMDVertexShaderLayerUsable()) code << "#define VSLayer\n"; if (CVS->needsRGBBindlessWorkaround()) code << "#define SRGBBindlessFix\n"; #if !defined(USE_GLES2) // shader compilation fails with some drivers if there is no precision // qualifier if (type == GL_FRAGMENT_SHADER) code << "precision mediump float;\n"; #else int range[2], precision; glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision); if (precision > 0) code << "precision highp float;\n"; else code << "precision mediump float;\n"; #endif code << "#define MAX_BONES " << SharedGPUObjects::getMaxMat4Size() << "\n"; code << getHeader(); std::ifstream stream(file_manager->getShader(file), std::ios::in); if (stream.is_open()) { const std::string stk_include = "#stk_include"; std::string line; while (std::getline(stream, line)) { const std::size_t pos = line.find(stk_include); // load the custom file pointed by the #stk_include directive if (pos != std::string::npos) { // find the start " std::size_t pos = line.find("\""); if (pos == std::string::npos) { Log::error("ShaderFilesManager", "Invalid #stk_include" " line: '%s'.", line.c_str()); continue; } std::string filename = line.substr(pos + 1); // find the end " pos = filename.find("\""); if (pos == std::string::npos) { Log::error("ShaderFilesManager", "Invalid #stk_include" " line: '%s'.", line.c_str()); continue; } filename = filename.substr(0, pos); // read the whole include file std::ifstream include_stream(file_manager->getShader(filename), std::ios::in); if (!include_stream.is_open()) { Log::error("ShaderFilesManager", "Couldn't open included" " shader: '%s'.", filename.c_str()); continue; } std::string include_line = ""; while (std::getline(include_stream, include_line)) { code << "\n" << include_line; } include_stream.close(); } else { code << "\n" << line; } } stream.close(); } else { Log::error("ShaderFilesManager", "Can not open '%s'.", file.c_str()); } Log::info("ShaderFilesManager", "Compiling shader : %s", file.c_str()); const std::string &source = code.str(); char const *source_pointer = source.c_str(); int len = source.size(); glShaderSource(id, 1, &source_pointer, &len); glCompileShader(id); GLint result = GL_FALSE; glGetShaderiv(id, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { // failed to compile int info_length; Log::error("ShaderFilesManager", "Error in shader %s", file.c_str()); glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length); if (info_length < 0) info_length = 1024; char *error_message = new char[info_length]; error_message[0] = 0; glGetShaderInfoLog(id, info_length, NULL, error_message); Log::error("ShaderFilesManager", error_message); delete[] error_message; } glGetError(); return id; } // loadShader
bool FBODefinition::Create() { #if MYFW_WINDOWS if( glGenFramebuffers == 0 ) { return false; } #endif #if MYFW_IOS || MYFW_ANDROID //return false; #endif #if !USE_D3D GLint maxsize; glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE, &maxsize ); LOGInfo( LOGTag, "CreateFBO - maxsize: %d\n", maxsize ); #if MYFW_ANDROID int range[2], precision; glGetShaderPrecisionFormat( GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision ); LOGInfo( LOGTag, "CreateFBO - High float precision: %d\n", precision ); LOGInfo( LOGTag, "CreateFBO - High float range min: %d\n", range[0] ); LOGInfo( LOGTag, "CreateFBO - High float range max: %d\n", range[1] ); glGetShaderPrecisionFormat( GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, range, &precision ); LOGInfo( LOGTag, "CreateFBO - Medium float precision: %d\n", precision ); LOGInfo( LOGTag, "CreateFBO - Medium float range min: %d\n", range[0] ); LOGInfo( LOGTag, "CreateFBO - Medium float range max: %d\n", range[1] ); glGetShaderPrecisionFormat( GL_FRAGMENT_SHADER, GL_LOW_FLOAT, range, &precision ); LOGInfo( LOGTag, "CreateFBO - Low float precision: %d\n", precision ); LOGInfo( LOGTag, "CreateFBO - Low float range min: %d\n", range[0] ); LOGInfo( LOGTag, "CreateFBO - Low float range max: %d\n", range[1] ); #endif if( m_TextureWidth > (unsigned int)maxsize || m_TextureHeight > (unsigned int)maxsize ) { // requested size is too big. return false; } MyAssert( m_FrameBufferID == 0 ); // get a framebuffer, render buffer and a texture from opengl. glGenFramebuffers( 1, &m_FrameBufferID ); checkGlError( "glGenFramebuffers" ); if( m_NeedColorTexture ) { m_pColorTexture = MyNew TextureDefinition(); glGenTextures( 1, &m_pColorTexture->m_TextureID ); m_pColorTexture->m_MinFilter = m_MinFilter; m_pColorTexture->m_MagFilter = m_MagFilter; m_pColorTexture->m_WrapS = GL_CLAMP_TO_EDGE; m_pColorTexture->m_WrapT = GL_CLAMP_TO_EDGE; m_pColorTexture->m_Width = m_Width; m_pColorTexture->m_Height = m_Height; } checkGlError( "glGenTextures" ); if( m_DepthBits != 0 ) { m_pDepthTexture = MyNew TextureDefinition(); MyAssert( m_DepthBits == 16 || m_DepthBits == 24 || m_DepthBits == 32 ); if( m_DepthIsTexture ) { glGenTextures( 1, &m_pDepthTexture->m_TextureID ); checkGlError( "glGenTextures" ); } else { glGenRenderbuffers( 1, &m_pDepthTexture->m_TextureID ); checkGlError( "glGenRenderbuffers" ); } m_pDepthTexture->m_Width = m_Width; m_pDepthTexture->m_Height = m_Height; } // create the texture if( m_pColorTexture && m_pColorTexture->m_TextureID != 0 ) { glBindTexture( GL_TEXTURE_2D, m_pColorTexture->m_TextureID ); //glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_TextureWidth, m_TextureHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL ); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_TextureWidth, m_TextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_MinFilter ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_MagFilter ); glBindTexture( GL_TEXTURE_2D, 0 ); checkGlError( "glBindTexture" ); } // create a depth renderbuffer. if( m_pDepthTexture && m_pDepthTexture->m_TextureID != 0 ) { #if !MYFW_OPENGLES2 GLint depthformat = GL_DEPTH_COMPONENT32; if( m_DepthBits == 24 ) depthformat = GL_DEPTH_COMPONENT24; else if( m_DepthBits == 16 ) depthformat = GL_DEPTH_COMPONENT16; #else GLint depthformat = GL_DEPTH_COMPONENT16; #endif if( m_DepthIsTexture ) { glBindTexture( GL_TEXTURE_2D, m_pDepthTexture->m_TextureID ); checkGlError( "glBindTexture" ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); checkGlError( "glTexParameteri" ); glTexImage2D( GL_TEXTURE_2D, 0, depthformat, m_TextureWidth, m_TextureHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0 ); //GL_DEPTH_COMPONENT, GL_FLOAT, 0 ); checkGlError( "glTexImage2D" ); glBindTexture( GL_TEXTURE_2D, 0 ); checkGlError( "glBindTexture" ); } else { glBindRenderbuffer( GL_RENDERBUFFER, m_pDepthTexture->m_TextureID ); glRenderbufferStorage( GL_RENDERBUFFER, depthformat, m_TextureWidth, m_TextureHeight ); checkGlError( "glRenderbufferStorageEXT" ); } } // attach everything to the FBO { MyBindFramebuffer( GL_FRAMEBUFFER, m_FrameBufferID, 0, 0 ); // attach color texture if( m_pColorTexture && m_pColorTexture->m_TextureID != 0 ) glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pColorTexture->m_TextureID, 0 ); // attach depth renderbuffer if( m_pDepthTexture && m_pDepthTexture->m_TextureID != 0 ) { if( m_DepthIsTexture ) { glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_pDepthTexture->m_TextureID, 0 ); } else { glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_pDepthTexture->m_TextureID ); } } MyBindFramebuffer( GL_FRAMEBUFFER, 0, 0, 0 ); checkGlError( "glBindFramebufferEXT" ); } // any problems? GLint status = glCheckFramebufferStatus( GL_FRAMEBUFFER ); checkGlError( "glCheckFramebufferStatus" ); if( status != GL_FRAMEBUFFER_COMPLETE ) { LOGInfo( LOGTag, "CreateFBO - error\n" ); //MyAssert( false ); Invalidate( true ); return false; } LOGInfo( LOGTag, "CreateFBO - complete (%d, %d)\n", m_TextureWidth, m_TextureHeight ); #else return false; #endif return true; }
bool COGLGraphicsContext::Initialize(uint32 dwWidth, uint32 dwHeight, BOOL bWindowed ) { DebugMessage(M64MSG_INFO, "Initializing OpenGL Device Context."); Lock(); CGraphicsContext::Get()->m_supportTextureMirror = false; CGraphicsContext::Initialize(dwWidth, dwHeight, bWindowed ); if( bWindowed ) { windowSetting.statusBarHeightToUse = windowSetting.statusBarHeight; windowSetting.toolbarHeightToUse = windowSetting.toolbarHeight; } else { windowSetting.statusBarHeightToUse = 0; windowSetting.toolbarHeightToUse = 0; } int depthBufferDepth = options.OpenglDepthBufferSetting; int colorBufferDepth = 32; int bVerticalSync = windowSetting.bVerticalSync; if( options.colorQuality == TEXTURE_FMT_A4R4G4B4 ) colorBufferDepth = 16; /* // init sdl & gl DebugMessage(M64MSG_VERBOSE, "Initializing video subsystem..."); if (CoreVideo_Init() != M64ERR_SUCCESS) return false; */ /* hard-coded attribute values */ const int iDOUBLEBUFFER = 1; /* set opengl attributes */ // CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, iDOUBLEBUFFER); // CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, bVerticalSync); // CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, colorBufferDepth); // CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, depthBufferDepth); // // /* set multisampling */ // if (options.multiSampling > 0) // { // CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLEBUFFERS, 1); // if (options.multiSampling <= 2) // CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 2); // else if (options.multiSampling <= 4) // CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 4); // else if (options.multiSampling <= 8) // CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 8); // else // CoreVideo_GL_SetAttribute(M64P_GL_MULTISAMPLESAMPLES, 16); // } // // /* Set the video mode */ // m64p_video_mode ScreenMode = bWindowed ? M64VIDEO_WINDOWED : M64VIDEO_FULLSCREEN; // if (CoreVideo_SetVideoMode(windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, colorBufferDepth, ScreenMode) != M64ERR_SUCCESS) // { // DebugMessage(M64MSG_ERROR, "Failed to set %i-bit video mode: %ix%i", colorBufferDepth, (int)windowSetting.uDisplayWidth, (int)windowSetting.uDisplayHeight); // CoreVideo_Quit(); // return false; // } // //#ifdef WIN32 // GLenum err = glewInit(); // if (GLEW_OK != err) // { // /* Problem: glewInit failed, something is seriously wrong. */ // fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); // } //#endif // // char caption[500]; // sprintf(caption, "%s v%i.%i.%i", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION)); // CoreVideo_SetCaption(caption); // SetWindowMode(); /* SDL_Surface* screen; SDL_Init(SDL_INIT_VIDEO); if (!(screen = SDL_SetVideoMode(1024, 768, 16, SDL_SWSURFACE ))) { SDL_QuitSubSystem( SDL_INIT_VIDEO ); return FALSE; } EGLNativeWindowType EGL_handle; EGLContext EGL_context; HDC EGL_device; EGLint EGL_version_major,EGL_version_minor; EGLint nConfigs; EGLConfig EGL_config; GLint success; const EGLint ConfigAttribs[] = { EGL_LEVEL, 0, EGL_DEPTH_SIZE, 16, EGL_STENCIL_SIZE, 0, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NATIVE_RENDERABLE, EGL_FALSE, EGL_NONE }; const EGLint ContextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; SDL_SysWMinfo info; SDL_VERSION(&info.version); SDL_GetWMInfo(&info); EGL_handle = (EGLNativeWindowType) info.window; EGL_device = GetDC(EGL_handle); printf("EGL Context Creation\n"); EGL_display = eglGetDisplay((EGLNativeDisplayType) EGL_device); if (EGL_display == EGL_NO_DISPLAY){ printf( "EGL Display Get failed: %s \n", EGLErrorString()); return FALSE; } if (!eglInitialize(EGL_display, &EGL_version_major, &EGL_version_minor)){ printf( "EGL Display Initialize failed: %s \n", EGLErrorString()); return FALSE; } if (!eglChooseConfig(EGL_display, ConfigAttribs, &EGL_config, 1, &nConfigs)){ printf( "EGL Configuration failed: %s \n", EGLErrorString()); return FALSE; } else if (nConfigs != 1){ printf( "EGL Configuration failed: nconfig %i, %s \n", nConfigs, EGLErrorString()); return FALSE; } EGL_surface = eglCreateWindowSurface(EGL_display, EGL_config, EGL_handle, NULL); if (EGL_surface == EGL_NO_SURFACE){ printf("EGL Surface Creation failed: %s will attempt without window... \n", EGLErrorString()); EGL_surface = eglCreateWindowSurface(EGL_display, EGL_config, NULL, NULL); if (EGL_surface == EGL_NO_SURFACE){ printf( "EGL Surface Creation failed: %s \n", EGLErrorString()); return FALSE; } } eglBindAPI(EGL_OPENGL_ES_API); EGL_context = eglCreateContext(EGL_display, EGL_config, EGL_NO_CONTEXT, ContextAttribs); if (EGL_context == EGL_NO_CONTEXT){ printf( "EGL Context Creation failed: %s \n", EGLErrorString()); return FALSE; } if (!eglMakeCurrent(EGL_display, EGL_surface, EGL_surface, EGL_context)){ printf( "EGL Make Current failed: %s \n", EGLErrorString()); return FALSE; }; eglSwapInterval(EGL_display, 1); */ #ifdef USE_SDL //// paulscode, added for switching between RGBA8888 and RGB565 // (part of the color banding fix) int bitsPP; if( Android_JNI_UseRGBA8888() ) bitsPP = 32; else bitsPP = 16; /* Set the video mode */ SDL_Surface* hScreen; printf( "Setting video mode %dx%d...\n", windowSetting.uDisplayWidth, windowSetting.uDisplayHeight ); // TODO: I should actually check what the pixelformat is, rather than assuming 16 bpp (RGB_565) or 32 bpp (RGBA_8888): // if (!(hScreen = SDL_SetVideoMode( windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, 16, SDL_HWSURFACE ))) if (!(hScreen = SDL_SetVideoMode( windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, bitsPP, SDL_HWSURFACE ))) { printf( "Problem setting videomode %dx%d: %s\n", windowSetting.uDisplayWidth, windowSetting.uDisplayHeight, SDL_GetError() ); SDL_QuitSubSystem( SDL_INIT_VIDEO ); return false; } #endif InitState(); InitOGLExtension(); sprintf(m_strDeviceStats, "%.60s - %.128s : %.60s", m_pVendorStr, m_pRenderStr, m_pVersionStr); TRACE0(m_strDeviceStats); DebugMessage(M64MSG_INFO, "Using OpenGL: %s", m_strDeviceStats); GLint precision,range; glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_LOW_FLOAT,&precision,&range); DebugMessage(M64MSG_INFO,"GLSL Vertex Shader lowp precision:%i range:%i",precision,range); glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_MEDIUM_FLOAT,&precision,&range); DebugMessage(M64MSG_INFO,"GLSL Vertex Shader mediump precision:%i range:%i",precision,range); glGetShaderPrecisionFormat(GL_VERTEX_SHADER,GL_HIGH_FLOAT,&precision,&range); DebugMessage(M64MSG_INFO,"GLSL Vertex Shader highp precision:%i range:%i",precision,range); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER ,GL_LOW_FLOAT,&precision,&range); DebugMessage(M64MSG_INFO,"GLSL Fragment Shader lowp precision:%i range:%i",precision,range); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_MEDIUM_FLOAT,&precision,&range); DebugMessage(M64MSG_INFO,"GLSL Fragment Shader mediump precision:%i range:%i",precision,range); glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER,GL_HIGH_FLOAT,&precision,&range); DebugMessage(M64MSG_INFO,"GLSL Fragment Shader highp precision:%i range:%i",precision,range); Unlock(); Clear(CLEAR_COLOR_AND_DEPTH_BUFFER); // Clear buffers UpdateFrame(); Clear(CLEAR_COLOR_AND_DEPTH_BUFFER); UpdateFrame(); m_bReady = true; status.isVertexShaderEnabled = false; return true; }